spring-jdbc 新增返回主键

分类:软件编程
阅读:475
作者:majingjing
发布:2017-01-18 13:28

昨天有同事在使用spring-jdbc写程序的时候出现了一个问题,新增之后返回主键设置参数相对的复杂.
虽然springJdbcTemplate提供了大量的模板方法,但是却发现在主键生成的方式上却没有一个很好的模板方法来实现代码的通用写法.
目前使用的版本是 spring-jdbc-4.3.4.RELEASE.jar , 我看了下官方现在最新是5.0,但是4.3.4版本也是2016才发布的.

比如理由官方提供的工厂方式来构造 PreparedStatementCreator 对象

  1. public int insert(String sql, Object... args) {
  2. PreparedStatementCreatorFactory factory = new PreparedStatementCreatorFactory(sql);
  3. factory.setReturnGeneratedKeys(true);
  4. PreparedStatementCreator psc = factory.newPreparedStatementCreator(args);
  5. GeneratedKeyHolder generatedKeyHolder = new GeneratedKeyHolder();
  6. jdbcTemplate.update(psc, generatedKeyHolder);
  7. return generatedKeyHolder.getKey().intValue();
  8. }

这个方式看上去是很完美的解决方案,但是通用性就不是很好,这样是没办法来设置参数的. 这个工厂方法提供的参数构造对象都必须得初始化参数的类型.这个就给我们写通用方法带来了一些困难.
看了下底层的实现方式,并没有对参数类型做过多的依赖处理,大部分逻辑放在了校验上,这个类型唯一起作用的地方就是设置Array,Collection类型的时候会做特殊处理.
微信截图_20170118132626.png
微信截图_20170118132729.png

相比我们程序的大部分情况是不会使用到这两个参数类型的.所以这个参数类型的参数完全可以通过实际参数值来获取.
官方并未提供简单的模板来使用,故自定义参数模板来实现

  1. /**
  2. * @author majinding888@foxmail.com
  3. * @date 2017-1-18 下午12:48:56
  4. */
  5. public class ArgsPreparedStatementCreator implements PreparedStatementCreator {
  6. private String sql;
  7. private Object[] args;
  8. public ArgsPreparedStatementCreator(String sql, Object... args) {
  9. this.sql = sql;
  10. this.args = args;
  11. }
  12. @Override
  13. public PreparedStatement createPreparedStatement(Connection con) throws SQLException {
  14. PreparedStatement ps = con.prepareStatement(sql, Statement.RETURN_GENERATED_KEYS);
  15. for (int i = 0; i < args.length; i++) {
  16. ps.setObject(i + 1, args[i]);
  17. }
  18. return ps;
  19. }
  20. }

其实数据库厂商都提供了setObject()来完成参数的设置.根本不需要想spring官方提供的设置那么复杂化.
微信截图_20170118131608.png

所以改造之后就可以完成通用调用

  1. public int insert(String sql, Object... args) {
  2. GeneratedKeyHolder keyHolder = new GeneratedKeyHolder();
  3. jdbcTemplate.update(new ArgsPreparedStatementCreator(sql, args), keyHolder);
  4. return keyHolder.getKey().intValue();
  5. }

当然要处理批量新增,返回keys方式就大同小异.