概述

Spring JDBC抽象框架core包提供了JDBC模板类,其中JdbcTemplate是core包的核心类,所以其他模板类都是基于它封装完成的,JDBC模板类是第一种工作模式。

JdbcTemplate类通过模板设计模式帮助我们消除了冗长的代码,只做需要做的事情(即可变部分),并且帮我们做哪些固定部分,如连接的创建及关闭。

JdbcTemplate类对可变部分采用回调接口方式实现,如ConnectionCallback通过回调接口返回给用户一个连接,从而可以使用该连接做任何事情、StatementCallback通过回调接口返回给用户一个Statement,从而可以使用该Statement做任何事情等等,还有其他一些回调接口

Spring除了提供JdbcTemplate核心类,还提供了基于JdbcTemplate实现的NamedParameterJdbcTemplate类用于支持命名参数绑定、 SimpleJdbcTemplate类用于支持Java5+的可变参数及自动装箱拆箱等特性。

JdbcTemplate类支持的回调类:

  • 预编译语句及存储过程创建回调:用于根据JdbcTemplate提供的连接创建相应的语句;

PreparedStatementCreator:通过回调获取JdbcTemplate提供的Connection,由用户使用该Conncetion创建相关的PreparedStatement;

CallableStatementCreator:通过回调获取JdbcTemplate提供的Connection,由用户使用该Conncetion创建相关的CallableStatement;

  • 预编译语句设值回调:用于给预编译语句相应参数设值;

PreparedStatementSetter:通过回调获取JdbcTemplate提供的PreparedStatement,由用户来对相应的预编译语句相应参数设值;

BatchPreparedStatementSetter:;类似于PreparedStatementSetter,但用于批处理,需要指定批处理大小;

  • 自定义功能回调:提供给用户一个扩展点,用户可以在指定类型的扩展点执行任何数量需要的操作;

ConnectionCallback:通过回调获取JdbcTemplate提供的Connection,用户可在该Connection执行任何数量的操作;

StatementCallback:通过回调获取JdbcTemplate提供的Statement,用户可以在该Statement执行任何数量的操作;

PreparedStatementCallback:通过回调获取JdbcTemplate提供的PreparedStatement,用户可以在该PreparedStatement执行任何数量的操作;

CallableStatementCallback:通过回调获取JdbcTemplate提供的CallableStatement,用户可以在该CallableStatement执行任何数量的操作;

  • 结果集处理回调:通过回调处理ResultSet或将ResultSet转换为需要的形式;

RowMapper:用于将结果集每行数据转换为需要的类型,用户需实现方法mapRow(ResultSet rs, int rowNum)来完成将每行数据转换为相应的类型。

RowCallbackHandler:用于处理ResultSet的每一行结果,用户需实现方法processRow(ResultSet rs)来完成处理,在该回调方法中无需执行rs.next(),该操作由JdbcTemplate来执行,用户只需按行获取数据然后处理即可。

ResultSetExtractor:用于结果集数据提取,用户需实现方法extractData(ResultSet rs)来处理结果集,用户必须处理整个结果集;

下面详细讲解jdbcTmeplate的CRUD操作:

(一)增加、删除、修改操作:

1)增加、更新、删除(一条sql语句)(sql固定,不需要参数):

(a) int update(final String sql)

其中sql参数为需要传入的插入sql语句。

(b)int update(PreparedStatementCreator psc)

    public void test() {
jdbcTemplate.update(new PreparedStatementCreator() { @Override
public PreparedStatement createPreparedStatement(Connection conn)
throws SQLException {
return conn.prepareStatement("insert into test(name) values('name1')");
}
});
}

(c)如果需要返回新插入数据的主键,采用如下方法(使用KeyHolder keyholder=new GeneratedKeyHolder();获得主键,jdbcTemplate和NamedParameterJdbcTemplate都可以通过此方法获得主键):

int update(PreparedStatementCreator psc, final KeyHolder generatedKeyHolder)

public void test() {
KeyHolder keyHolder = new GeneratedKeyHolder();
jdbcTemplate.update(new PreparedStatementCreator() { @Override
public PreparedStatement createPreparedStatement(Connection conn)
throws SQLException { return conn.prepareStatement("insert into test(name) values('name1')"); }
},keyHolder);
int i = keyHolder.getKey().intValue();//这就是刚插入的数据的主键
}

2)增加、更新、删除(一条sql语句)(sql需要注入参数填充‘?’):

  (a)int update(String sql, PreparedStatementSetter pss)

public void test() {
String sql = "insert into test(name) values (?)";
//返回的是更新的行数
int count = jdbcTemplate.update(sql, new PreparedStatementSetter(){ @Override
public void setValues(PreparedStatement pstmt)
throws SQLException {
pstmt.setObject(1, "name4");
}
});
}

(b)int update(String sql, Object[] args, int[] argTypes)

其中参数含义:   sql:预处理sql语句; args:sql需要注入的参数; argTypes:需要注入的sql参数的JDBC类型(java.sql.Types中来获取类型的常量);

    public void test() {
String sql = "insert into test(name,age,create_date) values (?,?,?)";
Date now = new Date(System.currentTimeMillis());
//返回的是更新的行数
int count = jdbcTemplate.update(sql, new Object[]{"小明",14,now}, new int[]{Types.VARCHAR,Types.INTEGER,Types.DATE});
}

(c)int update(String sql, Object... args)

其实内部还是调用方法a实现的,JdbcTemplate提供这种更简单的方式“update(String sql, Object... args)”来实现设值,所以只要当使用该种方式不满足需求时才应使用PreparedStatementSetter(上面方法a)。

public void test() {
String sql = "insert into test(name,age,create_date) values (?,?,?)";
Date now = new Date(System.currentTimeMillis());
//返回的是更新的行数
int count = jdbcTemplate.update(sql, "小明", 14, now);
}
public void test() {
String sql = "insert into test(name,age,create_date) values (?,?,?)";
Date now = new Date(System.currentTimeMillis());
//返回的是更新的行数
int count = jdbcTemplate.update(sql, new Object[]{"小明",14,now});
}

这两种实际上调用的都是该方法,由此可见Object...args实际上就是可变的数组,而数组长度是固定的,必须先定义一个数组,而Object...args在传递时参数可以任意,所以也可以传递一个固定的Object数组。

(d)int update(PreparedStatementCreator psc)

使用该方法可以自己使用原始jdbc方式给预编译sql注入参数,来进行增加、删除、更新操作:

public void test(final Customer customer) {//参数也是局部变量,也必须用final修饰,内部类中才能访问(全局变量不用)
//方法局部必须是final的,匿名内部类中才能引用
final String sql = "insert into test(name,age,create_date) values (?,?,?)";
Date now = new Date(System.currentTimeMillis());
//返回的是更新的行数
int count = jdbcTemplate.update(new PreparedStatementCreator() { @Override
public PreparedStatement createPreparedStatement(Connection conn)
throws SQLException {
PreparedStatement ps = conn.prepareStatement(sql);
ps.setString(1, customer.getName());
ps.setInt(2, customer.getAge());
ps.setDate(3, customer.getCreateDate()); return ps;
}
}); }

如果需要返回插入的主键,只能用此方法,增加KeyHolder参数:

public void test(final Customer customer) {//参数也是局部变量,也必须用final修饰,内部类中才能访问(全局变量不用)
KeyHolder keyHolder = new GeneratedKeyHolder();
//方法局部必须是final的,匿名内部类中才能引用
final String sql = "insert into test(name,age,create_date) values (?,?,?)";
Date now = new Date(System.currentTimeMillis());
//返回的是更新的行数
int count = jdbcTemplate.update(new PreparedStatementCreator() { @Override
public PreparedStatement createPreparedStatement(Connection conn)
throws SQLException {
PreparedStatement ps = conn.prepareStatement(sql,Statement.RETURN_GENERATED_KEYS); //有的数据库版本不一样,需要添加第二个参数,不然会报错;
          ps.setString(1, customer.getName());
          ps.setInt(2, customer.getAge());
          ps.setDate(3, customer.getCreateDate());
          return ps;
        }
    },keyHolder);
    
    int i = keyHolder.getKey().intValue();//这就是刚插入的数据的主键 }

3)批量增加、删除、更新数据(多条sql语句)

  (a)批量执行多条sql(固定的sql,不需要注入参数,但是sql格式不固定)

      int[] batchUpdate(final String[] sql)

参数是一个String数组,存放多条sql语句;返回值是int数组,即每条sql更新影响的行数。

  (b)批量执行多条sql(预处理sql,需要注入参数)

    int[] batchUpdate(String sql, final BatchPreparedStatementSetter pss)

参数sql:一条预处理sql(如果是批量处理预处理sql,那么sql的格式就是固定的,只填充参数而已);第二个参数就是回调类,前面有统一介绍回调类。

举两个例子,一个更新,一个插入:

批量插入:
public void test(final List<Customer> customer) {//参数也是局部变量,也必须用final修饰,内部类中才能访问(全局变量不用) String sql = "insert into test(name,age,create_date) values (?,?,?)";
//返回的是更新的行数
int[] count = jdbcTemplate.batchUpdate(sql, new BatchPreparedStatementSetter() { @Override
public void setValues(PreparedStatement ps, int i)
throws SQLException {
//注入参数值
ps.setString(1, customer.get(i).getName());
ps.setInt(2, customer.get(i).getAge());
ps.setDate(3, customer.get(i).getCreateDate());
} @Override
public int getBatchSize() {
//批量执行的数量
return customer.size();
}
}); }
批量更新:
public void test(final List<Customer> customer) {//参数也是局部变量,也必须用final修饰,内部类中才能访问(全局变量不用)
String sql = "update test set name = ?,age = ? where id = ?";
//返回的是更新的行数
int[] count = jdbcTemplate.batchUpdate(sql, new BatchPreparedStatementSetter() { @Override
public void setValues(PreparedStatement ps, int i)
throws SQLException {
//注入参数值
ps.setString(1, customer.get(i).getName());
ps.setInt(2, customer.get(i).getAge());
ps.setInt(3, customer.get(i).getId());
} @Override
public int getBatchSize() {
//批量执行的数量
return customer.size();
}
}); }

  (c)批量处理多条预处理sql语句还有下面几种简单方法(参数和前面类似,这里就不详解):

int[] batchUpdate(String sql, List<Object[]> batchArgs);

int[] batchUpdate(String sql, List<Object[]> batchArgs, int[] argTypes);

jdbcTemplate学习(一)的更多相关文章

  1. JdbcTemplate学习笔记

    JdbcTemplate学习笔记 1.使用JdbcTemplate的execute()方法执行SQL语句 Java 代码 jdbcTemplate.execute("CREATE TABLE ...

  2. Spring之JDBCTemplate学习

    一.Spring对不同的持久化支持: Spring为各种支持的持久化技术,都提供了简单操作的模板和回调 ORM持久化技术 模板类 JDBC org.springframework.jdbc.core. ...

  3. JdbcTemplate学习笔记(更新插入删除等)

    1.使用JdbcTemplate的execute()方法执行SQL语句 jdbcTemplate.execute("CREATE TABLE USER (user_id integer, n ...

  4. Spring3.2.9 + JdbcTemplate 学习

    applicationContext.xml <?xml version="1.0" encoding="UTF-8"?> <beans xm ...

  5. jdbcTemplate学习(四)

    前面三节讲了jdbcTemplate的使用,这一节讲解NamedParameterJdbcTemplate的使用方法: NamedParameterJdbcTemplate类是基于JdbcTempla ...

  6. jdbcTemplate学习(三)

    上一节讲的查询方法,映射结果集为对象时,需要一个个set属性值,比较麻烦,下面讲解使用BeanPropertyRowMapper来将查询结果简单映射成对象: 使用Spring的JdbcTemplate ...

  7. jdbcTemplate学习(二)

    前面讲了增加.删除.更新操作,这节讲一下查询. 查询操作: (一)查询一个值(不需要注入参数) queryForObject(String sql, Class<T> requiredTy ...

  8. spring data之JDBCTemplate学习笔记

    一.spring 数据访问哲学 1.为避免持久化的逻辑分散在程序的各个组件中,数据访问的功能应到放到一个或多个专注于此的组件中,一般称之为数据访问对象(data access object,DAO). ...

  9. Spring jdbctemplate学习笔记

    /*List<?> config = getDB(" select t.datavalue from sys_config t where t.configid = '15' & ...

随机推荐

  1. Hibernate 关于实体映射常用注解

    注解 类注解(写在类上面的) @Entity       标明实体类 @Table(name="数据库标明")      生成数据库时的表名由这个决定 @DynamicInsert ...

  2. numpy nonzero与isnan

    nonzero 直接看例子: In [83]: x = np.array([[1,0,0], [0,2,0], [1,1,0]]) In [84]: x.shape Out[84]: (3L, 3L) ...

  3. [转]理解Object.assign

    本节内容我们继续探讨关于ES2015的一些新的内容,Object.assign函数的使用,使用该函数我们可以快速的复制一个或者多个对象到目标对象中,本文内容涉及es6,es7相关的对象复制的内容,以及 ...

  4. 华丽导航CSS下拉菜单特效

    华丽导航CSS下拉菜单特效,华丽导航,导航特效,CSS,下拉菜单,华丽特效. 代码地址:http://www.huiyi8.com/sc/26811.html 风景图片网:http://www.hui ...

  5. v2.0 组件通信的总结

    在vue.js现在比较流行,层出不穷的js框架越来越强调数据绑定,组件化开发. 正在给公司做一个管理后台,基本思路是编写几个通用组件,采用单页面应用的形式完成: 结构大致如下: mainVue lef ...

  6. LeetCode OJ:Minimum Depth of Binary Tree(二叉树的最小深度)

    Given a binary tree, find its minimum depth. The minimum depth is the number of nodes along the shor ...

  7. git教程3-添加远程库与从远程库拷贝

    一.添加到github 1.github上创建新的库learngit.git 2.git remote add origin git@github.com:moisiet/learngit.git  ...

  8. SVN客户端与服务器端搭建

    一.客户端安装 1.点击安装程序 2.修改svn安装位置 3.开始安装 4.安装完成 5.回到左面  右键出现svn检出 tortoiSVN  表示安装成功  二.SVN服务端安装 1.点击服务端安装 ...

  9. SQL夯实基础(二):连接操作中使用on与where筛选的差异

    一.on筛选和where筛选 在连接查询语法中,另人迷惑首当其冲的就要属on筛选和where筛选的区别了,如果在我们编写查询的时候, 筛选条件的放置不管是在on后面还是where后面, 查出来的结果总 ...

  10. Codeforces 808D. Array Division

    题目大意 给定你一个长为\(n\)的序列,问能否在最多一次取出某一元素然后插入到某一点后可以将整个序列分成两段使得其两段的元素之和相同. \(n \leq 10^5\) 题解 发现插入操作实际上是让某 ...