什么是JdbcTemplate
是Spring中data-access模块中的一个工具类,对jdbc的操作进行了轻量级的封装,可以取代jdbc、mybatis等操作数据库;
JdbcTemplate中包含一个dataSource属性(数据源),初始化该属性后,可以调用工具类中的方法操作数据库,大概的示意图如下:
怎么用JdbcTemplate
1、准备工作,导入需要的jar (这个博客只做junit测试的Demo):
- 数据库驱动jar :mysql-connector-java......
- spring核心容器core、context;
- spring集成jdbc 的 jar:spring-jdbc..., 事务控制的jar:spring-tx...
- 如果要使用另外的数据库连接池,还需导入相应的jar: 如druid, c3p0...
<!-- 配置属性值 -->
<properties>
<charset>UTF-8</charset>
<jdk.version>1.7</jdk.version>
<struts2.version>2.3.24</struts2.version>
<spring.version>4.1.0.RELEASE</spring.version>
<project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
<argLine>-Dfile.encoding=UTF-8</argLine>
</properties>
<dependencies>
<!-- 测试 -->
<dependency>
<groupId>junit</groupId>
<artifactId>junit</artifactId>
<version>4.12</version>
<scope>test</scope>
</dependency>
<!-- mysql数据库驱动 -->
<dependency>
<groupId>mysql</groupId>
<artifactId>mysql-connector-java</artifactId>
<version>5.1.32</version>
</dependency>
<!-- spring核心容器core子模块的依赖信息 -->
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-core</artifactId>
<version>${spring.version}</version>
</dependency>
<!-- spring核心容器context子模块的依赖信息 -->
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-context</artifactId>
<version>${spring.version}</version>
</dependency>
<!-- spring核心容器context子模块的依赖jar包的依赖信息 -->
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-context-support</artifactId>
<version>${spring.version}</version>
</dependency>
<!-- spring集成jdbc的jar,该包中提供了JdbcTemplate工具类 -->
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-jdbc</artifactId>
<version>${spring.version}</version>
</dependency>
<!-- spring中事务控制的jar -->
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-tx</artifactId>
<version>${spring.version}</version>
</dependency>
</dependencies>
2、配置applicationContext.xml 中的数据库连接池
- 如果是springframe中的连接池:
<bean id="dataSource" class="org.springframework.jdbc.datasource.DriverManagerDataSource">
<property name="driverClassName" value="com.mysql.jdbc.Driver" />
<property name="url" value="jdbc:mysql://localhost:3306/数据库名?useUnicode=true&characterEncoding=utf8" />
<property name="username" value="用户名" />
<property name="password" value="密码" />
</bean>
- 如果是 c3p0
<bean id="dataSource" class="com.mchange.v2.c3p0.ComboPooledDataSource" destroy-method="close">
<property name="driverClass" value="com.mysql.jdbc.Driver" />
<property name="jdbcUrl" value="jdbc:mysql://localhost:3306/数据库名?useUnicode=true&characterEncoding=utf8" />
<property name="user" value="用户名" />
<property name="password" value="密码" />
</bean>
- com.alibaba.druid
<bean id="dataSource" class="com.alibaba.druid.pool.DruidDataSource">
<!-- 与数据库建立连接的基本信息 -->
<property name="driverClassName" value="com.mysql.jdbc.Driver"></property>
<property name="url" value="jdbc:mysql://localhost:3306/数据库名?useUnicode=true&characterEncoding=utf8"></property>
<property name="username" value="用户名"></property>
<property name="password" value="密码"></property>
<!-- 数据库连接池的基本信息 -->
<property name="maxActive" value="50"></property>
<property name="minIdle" value="1"></property>
<property name="initialSize" value="5"></property>
<property name="maxWait" value="60000"></property>
</bean>
下面贴一个完整的applicationContext.xml配置:
<?xml version="1.0" encoding="UTF-8"?>
<!-- xmlns指的是命名空间,下面存放着各个版本的约束文件 -->
<!-- xmlns:xsi指的是标签符合w3c的规范 -->
<!-- xsi:schemaLocation:约束文件的路径,命名空间与约束文件的全路径组成 -->
<beans xmlns="http://www.springframework.org/schema/beans"
xmlns:context="http://www.springframework.org/schema/context"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation=
"http://www.springframework.org/schema/beans
http://www.springframework.org/schema/beans/spring-beans.xsd
http://www.springframework.org/schema/context
http://www.springframework.org/schema/context/spring-context.xsd">
<!-- 数据源 -->
<bean id="dataSource" class="org.springframework.jdbc.datasource.DriverManagerDataSource">
<property name="driverClassName" value="com.mysql.jdbc.Driver" />
<property name="url" value="jdbc:mysql://localhost:3306/数据库名?useUnicode=true&characterEncoding=utf8" />
<property name="username" value="用户名" />
<property name="password" value="密码" />
</bean>
<!-- 加载spring的工具类JdbcTemplate为bean组件 -->
<bean id="jdbcTemplate" class="org.springframework.jdbc.core.JdbcTemplate">
<property name="dataSource" ref="dataSource"></property>
</bean>
<!-- 通过spring的依赖注入设定Dao类JdbcTemplate属性 -->
<bean id="userDao" class="com.chaol.dao.impl.LsjmUserDaoImpl">
<property name="jdbcTemplate" ref="jdbcTemplate"></property>
</bean>
</beans>
在上面的配置文件中已经依赖注入LsjmUserDaoImpl类中的jdbcTemplate属性,可以调用工具类的方法操作jdbc了(具体代码在下方),
- 查询一条数据:Object query(String sql,Object[] obs, ResultSetExtractor rs)
- sql : 查询语句,可以带预处理 即 ?
- obs:预处理数据,这个参数可选;有参数写上,没有参数可以不写或者写成new Object[] {}也可以
- rs:一个接口,这里写成匿名内部类的形式,需要实现其实的方法: extractData(ResultSet rset),参数rset即为查询的返回值
- 查询集合:List query(String sql,Object[] obs, RowMapper rm)
- rm:同样是接口,需要实现方法:mapRow(ResultSet rs, int rowNum),rowNum参数表示当前迭代的下标, rs表示当前迭代的返回值
- 批量操作:int[] batchUpdate(sql, BatchPreparedStatementSetter bps)
- bps:接口,需要实现两个方法 setValues(PreparedStatement ps, int i) ,ps预处理数据,i 表示当前循环; getBatchSize() : 指定批量操作循环的长度
- queryForList 、 queryForInt 、queryForMap 、queryForObject 这些查询的方法 不做一 一解释了
package com.chaol.dao.impl;
import java.sql.PreparedStatement;
import java.sql.ResultSet;
import java.sql.SQLException;
import java.util.List;
import org.springframework.dao.DataAccessException;
import org.springframework.jdbc.core.BatchPreparedStatementSetter;
import org.springframework.jdbc.core.JdbcTemplate;
import org.springframework.jdbc.core.ResultSetExtractor;
import org.springframework.jdbc.core.RowMapper;
import com.chaol.dao.LsjmUserDao;
import com.chaol.vo.LsjmUser;
public class LsjmUserDaoImpl implements LsjmUserDao {
private JdbcTemplate jdbcTemplate;
// 查询一条记录
public LsjmUser getUserByName() {
String sql = "select * from lsjm_user where uname = '300'";
return jdbcTemplate.query(sql, new Object[]{}, new ResultSetExtractor<LsjmUser>(){
public LsjmUser extractData(ResultSet rs) throws SQLException, DataAccessException {
if(rs.next()){
LsjmUser user = new LsjmUser();
user.setUname(rs.getString("uname"));
user.setAddress(rs.getString("address"));
return user;
}
return null;
}
});
}
// 查询集合
public List<LsjmUser> getUser() {
String sql = "select * from lsjm_user";
return jdbcTemplate.query(sql, new RowMapper<LsjmUser>(){
// 方法内部实现了对查询集合的遍历,rowNum表示当前下标
public LsjmUser mapRow(ResultSet rs, int rowNum) throws SQLException {
System.out.println(rowNum);
LsjmUser user = new LsjmUser();
user.setUname(rs.getString("uname"));
return user;
}
});
}
// 单条数据的 增、删、改 ,都是用update(String sql, Object[] obs)方法
// 第二个参数是预处理数据数组,(可选)
public int update(){
String sql = "update lsjm_user set address = ? where uname = ?";
return jdbcTemplate.update(sql,new Object[]{"updateTest", "300"});
}
public int insert(){
String sql = "insert into lsjm_user (uname,pwd) values (?,?)";
return jdbcTemplate.update(sql,new Object[]{"jdbcTemplate", "jdbcTemplate"});
}
public int delete(){
String sql = "delete from lsjm_user where uname='jdbcTemplate'";
return jdbcTemplate.update(sql);
}
// 批量操作 增、删、改
public int[] banchInsert(final List<LsjmUser> list){
String sql = "insert into lsjm_user (uname,pwd) values (?,?)";
return jdbcTemplate.batchUpdate(sql, new BatchPreparedStatementSetter() {
// 循环操作,当前是i,长度由下面的getBatchSize()方法指定
public void setValues(PreparedStatement ps, int i) throws SQLException {
ps.setString(1, list.get(i).getUname());
ps.setString(2, list.get(i).getPwd());
}
// 指定批量操作的长度
public int getBatchSize() {
return list.size();
}
});
}
public int[] banchupdate(final List<LsjmUser> list){
String sql = "update lsjm_user set pwd = ? where uname = ?";
return jdbcTemplate.batchUpdate(sql, new BatchPreparedStatementSetter() {
// 循环操作,当前是i,长度由下面的getBatchSize()方法指定
public void setValues(PreparedStatement ps, int i) throws SQLException {
ps.setString(1, list.get(i).getPwd());
ps.setString(2, list.get(i).getUname());
}
// 指定批量操作的长度
public int getBatchSize() {
return list.size();
}
});
}
public int[] banchDelete(final List<LsjmUser> list){
String sql = "delete from lsjm_user where uname = ?";
return jdbcTemplate.batchUpdate(sql, new BatchPreparedStatementSetter() {
// 循环操作,当前是i,长度由下面的getBatchSize()方法指定
public void setValues(PreparedStatement ps, int i) throws SQLException {
ps.setString(1, list.get(i).getUname());
}
// 指定批量操作的长度
public int getBatchSize() {
return list.size();
}
});
}
public JdbcTemplate getJdbcTemplate() {
return jdbcTemplate;
}
public void setJdbcTemplate(JdbcTemplate jdbcTemplate) {
this.jdbcTemplate = jdbcTemplate;
}
}
上述中,是在Dao类中把JdbcTemplate作为类的全局变量,生成set、get方法后,通过spring 依赖注入初始化JdbcTemplate 属性,从而调用类中的方法,
还有一种方法,就是Dao类继承JdbcTemplate 类,如:
public class LsjmUserDaoImpl1 extends JdbcTemplate implements LsjmUserDao {
// 查询一条记录
public LsjmUser getUserByName() {
String sql = "select * from lsjm_user where uname = '300'";
// query是父类的方法
return query(sql, new Object[]{}, new ResultSetExtractor<LsjmUser>(){
public LsjmUser extractData(ResultSet rs) throws SQLException, DataAccessException {
if(rs.next()){
LsjmUser user = new LsjmUser();
user.setUname(rs.getString("uname"));
user.setAddress(rs.getString("address"));
return user;
}
return null;
}
});
}
}
此时的配置文件为(因为dataSource是父类JdbcTemplate的一个属性,这里做spring 依赖注入处理):
<!-- 数据源 -->
<bean id="dataSource" class="org.springframework.jdbc.datasource.DriverManagerDataSource">
<property name="driverClassName" value="com.mysql.jdbc.Driver" />
<property name="url" value="jdbc:mysql://localhost:3306/数据库名?useUnicode=true&characterEncoding=utf8" />
<property name="username" value="用户名" />
<property name="password" value="密码" />
</bean>
<bean id="userDao" class="com.chaol.dao.impl.LsjmUserDaoImpl1">
<property name="dataSource" ref="dataSource"></property>
</bean>