前言
Spring JdbcTemplate是Spring Framework提供的一个强大的数据库访问工具,它简化了数据库操作的过程,为开发者提供了一个高级的数据库访问抽象层。
JdbcTemplate是Spring JDBC模块中的一个核心类,它位于
org.springframework.jdbc.core
包中。JdbcTemplate通过封装JDBC的核心功能,如数据库连接管理、SQL执行、参数绑定、结果集提取、异常处理等,使得数据库操作变得更加简单和高效。
1 使用Spring JDBC 模版
- Spring的JDBC框架将数据访问的过程中获取连接、释放资源、异常处理、遍历查询结果等必须的样板代码封装隐藏到模板类之下,从而简化我们的JDBC 代码.
- Spring针对JDBC提供了3个模板类
- JdbcTemplate:Spring 里最基本的 JDBC 模板,利用 JDBC 和简单的索引参数查询提供对数据库的简单访问。
- NamedParameterJdbcTemplate:能够在执行查询时把值绑定到SQL里的命名参数,而不是使用索引参数,这有利于简化动态组合条件查询的实现,也不容易搞混参数
- SimpleJdbcTemplate:利用Java 5的特性,比如自动装箱、泛型(generic)和可变参数列表来简化JDBC模板的使用。
1.1 使用JdbcTemplate
- 将JdbcTemplate配置成bean
- 注入DataSource
<bean id="jdbcTemplate" class="….jdbc.core.JdbcTemplate">
<property name="dataSource" ref="dataSource"/>
</bean>
- 案例:完成scott中员工信息的增删查改操作
EmpDao:
public interface EmpDao {
List<Emp> search();
List<Emp> search(Emp e);
Emp findById(int empno);
void save(Emp e);
void update(Emp e);
void delete(int empno);
}
Dao的实现类:
public class EmpDaoJdbcTemplate implements EmpDao {
@Resource(name="jdbcTemplate")
private JdbcTemplate jdbcTemplate;
……
}
- 案例:员工信息的插入操作
- JdbcTemplate
- public int update(String sql,Object...args)
public void save(Emp e) {
String sql = "insert into emp (empno,ename,deptno) values (?,?,?)";
Object[] params =
newObject[]{e.getEmpno(), e.getEname(), e.getDept().getDeptno()};
jdbcTemplate.update(sql, params);
}
传递参数时,可以按顺序依次传参,也可以封装成一个Object数组进行传参。
测试类:
@Test
public void testSave() throws Exception {
Emp emp = new Emp(1012,"员工测试",new Dept(40));
dao.save(emp);
}
- 案例:实现无参的search方法
- JdbcTemplate的query方法
- 一个字符串,SQL语句
- 一个RowMapper对象,从ResultSet里提取数值并构造一个实体对象返回,在这里就是员工对象。
public List<Emp> search() {
String sql = "select e.empno,e.ename,d.deptno,d.dname from emp e inner join dept d on e.deptno = d.deptno ";
RowMapper rowMapper = new ParameterizedRowMapper<Emp>()
{
@Override
public Emp mapRow(ResultSet rs, int rowNum) …{
Emp e = new Emp();
e.setEmpno(rs.getInt("empno"));
e.setEname(rs.getString("ename"));
Dept d = new Dept();
d.setDeptno(rs.getInt("deptno"));
d.setDname(rs.getString("dname"));
e.setDept(d);
return e;
}
};
List<Emp> list = jdbcTemplate.query(sql,rowMapper);
return list;
}
- search()、findById()和search(Emp e)都需要使用同一个RowMapper对象
- 定义成EmpDao接口的一个公共静态常量属性
public static final RowMapper rowMapper = new ParameterizedRowMapper<Emp>() {
@Override
public Emp mapRow(ResultSet rs, int rowNum) throws SQLException {
Emp e = new Emp();
e.setEmpno(rs.getInt("empno"));
e.setEname(rs.getString("ename"));
Dept d = new Dept();
d.setDeptno(rs.getInt("deptno"));
d.setDname(rs.getString("dname"));
e.setDept(d);
return e;
}
};
List<Emp> list = jdbcTemplate.query(sql,rowMapper);//精减后的代码
- 案例:实现findById方法
- findById方法与search相同,仅有两点不同
- 需要传递查询条件
- 仅返回一个员工对象而不是一个员工对象集合
public Emp findById(int empno) {
String sql = "select e.empno,e.ename,d.deptno,d.dname from emp e
inner join dept d on e.deptno = d.deptno where empno = ?";
List<Emp> list = jdbcTemplate.query(sql, rowMapper,empno);
return list.size()>0?(Emp)list.get(0):null;
}
- 案例:实现search(Emp e)方法
- 根据用户在多个查询条件中选填后得到动态组合查询的效果。
- 两个查询条件,员工姓名和所属部门。
- 无条件查询
- 仅填写姓名,进行模糊查询
- 仅选择部门,查询谋部门的所有员工
- 既填写姓名又选择部门,查询谋部门符合姓名条件的员工信息
public List<Emp> search(Emp e) {
StringBuilder sql = new StringBuilder("select empno,ename,d.deptno,dname from…");
List plist = new ArrayList();
if(e!=null){
if(e.getEname()!=null && e.getEname().trim().length()!=0){
sql.append(" and e.ename like ?");
plist.add("%"+e.getEname()+"%");
}
if(e.getDept()!=null && e.getDept().getDeptno()!=null
&& e.getDept().getDeptno()>0){
sql.append(" and d.deptno = ?");
plist.add(e.getDept().getDeptno());
}}
Object[] params = plist.toArray();
List<Emp> list = jdbcTemplate.query(sql.toString(),params,rowMapper);
return list;}
如果符合条件就拼接对应的where条件,达到多条件查询的效果。
1.2 使用NamedParameterJdbcTemplate
- 案例:save方法实现中使用了索引参数
- 注意参数在SQL语句里的次序
- 以正确次序设置对应参数的值
- 改变参数的次序,值的次序也必须随之改变
- 使用命名参数
insert into emp ( empno , ename , deptno )
values ( :empno, :ename, :deptno)
- 次序是没有关系的
- 用名称绑定每个值
- 参数次序改变,不需要修改参数绑定的代码
代码实现:
- JDBC 模板:NamedParameterJdbcTemplate
spring.xml(spring的配置文件):
<bean id="namedParameterJdbcTemplate"
class="…jdbc.core.namedparam.NamedParameterJdbcTemplate">
<constructor-arg ref="dataSource"/>
</bean>
java代码:
@Component("empDaoNamedParam")
public class EmpDaoNamedParameter implements EmpDao {
@Resource(name="namedParameterJdbcTemplate")
private NamedParameterJdbcTemplate jdbcTemplate;
……
}
案例:
- 案例:使用命名参数的save方法
- 案例:只有一个参数的findById方法
- 案例:search方法,查询所有员工
public int save(Emp e) {
String sql = "insert into emp (empno,ename,deptno) " +
"values (:empno,:ename,:deptno)";
Map params = new HashMap();
params.put("empno", e.getEmpno());
params.put("ename", e.getEname());
params.put("deptno", e.getDept().getDeptno());
return jdbcTemplate.update(sql, params);
}
public Emp findById(int empno) {
String sql = "select e.empno,e.ename,d.deptno,d.dname from emp e inner join dept d on e.deptno = d.deptno where empno = :empno";
Map params = new HashMap();
params.put("empno", empno);
List<Emp> list = jdbcTemplate.query(sql, params,rowMapper);
return list.size()>0?(Emp)list.get(0):null;
}
public List<Emp> search() {
String sql = "select e.empno,e.ename,d.deptno,d.dname from
emp e inner join dept d on e.deptno = d.deptno ";
List<Emp> list = jdbcTemplate.query(sql,new HashMap(),rowMapper);
return list;
}
2 使用Spring 对 JDBC的 DAO支持类
- 存在问题
- JDBC的全部DAO类,需要一个JdbcTemplate属性和一个设置方法
- 把JdbcTemplate Bean装配到每个DAO的JdbcTemplate属性
- 多个DAO,产生很多重复代码
- 解决方案
- 全部DAO 对象创建一个通用父类 在其中设置 JdbcTemplate 属性,
- 全部 DAO 继承这个类,使用父类的JdbcTemplate进行数据访问,
- Spring恰好提供了这样一些基类。
2.1 使用JdbcDaoSupport
- Spring 的 JdbcDaoSupport 就是用于编写基于JDBC 的DAO 类的基类
- 自己的DAO类继承它即可
package dao.support;
public class EmpDaoJdbcSupport extends JdbcDaoSupport implements EmpDao{
……省略方法
}
public int save(Emp e) {
String sql = "insert into emp (empno,ename,deptno) values (?,?,?)";
Object[] params = new Object[]{
e.getEmpno(),e.getEname(),e.getDept().getDeptno()};
//调用父类的方法
return getJdbcTemplate().update(sql, params);
}
- JdbcTemplate属性定义在父类JdbcDaoSupport中
- 无法使用注解,因为添加注解需要修改源代码
- 只能使用xml方式配置
<bean id="empDaoJdbcSupport" class="dao.support.EmpDaoJdbcSupport">
<property name="jdbcTemplate" ref="jdbcTemplate"></property>
</bean>
2.2 使用NamedParameterJdbcDaoSupport
- 使用命名参数形式
- 让Dao类继承NamedParameterJdbcDaoSupport类
package dao.support;
public class EmpDaoNamedJdbcSupport extends NamedParameterJdbcDaoSupport
implements EmpDao{
……省略方法
}
- 调用父类的getNamedParameterJdbcTemplate()方法返回一个NamedParameterJdbcTemplate对象
- 可以使用命名参数的形式编写dao操作
public int save(Emp e) {
String sql = "insert into emp (empno,ename,deptno) values "+
"(:empno,:ename,:deptno)";
Map params = new HashMap();
params.put("empno", e.getEmpno());
params.put("ename", e.getEname());
params.put("deptno", e.getDept().getDeptno());
return getNamedParameterJdbcTemplate().update(sql, params);
}
- bean配置
<bean id="empDaoNamedJdbcSupport" class="dao.support.EmpDaoNamedJdbcSupport">
<property name="jdbcTemplate" ref="jdbcTemplate"/>
</bean>
总结
主要介绍如何使用Spring JDBC模版,以及使用Spring对JDBC的DAO支持类