博客
关于我
强烈建议你试试无所不能的chatGPT,快点击我
SpringJDBC解析3-回调函数(update为例)
阅读量:6717 次
发布时间:2019-06-25

本文共 4729 字,大约阅读时间需要 15 分钟。

PreparedStatementCallback作为一个接口,其中只有一个函数doInPrepatedStatement,这个函数是用于调用通用方法execute的时候无法处理的一些个性化处理方法,在update中的函数实现:

protected int update(final PreparedStatementCreator psc, final PreparedStatementSetter pss)          throws DataAccessException {        logger.debug("Executing prepared SQL update");      return execute(psc, new PreparedStatementCallback
() { public Integer doInPreparedStatement(PreparedStatement ps) throws SQLException { try { if (pss != null) { pss.setValues(ps); } int rows = ps.executeUpdate(); if (logger.isDebugEnabled()) { logger.debug("SQL update affected " + rows + " rows"); } return rows; } finally { if (pss instanceof ParameterDisposer) { ((ParameterDisposer) pss).cleanupParameters(); } } } }); }

其中真正执行SQL的ps.executeUpdate并没有太多需要讲的,但是,对于设置输入参数的函数pss.setValues(ps),可以分析一下。

在没有分析源码之前,我们至少可以知道其功能,回顾下Spring中使用SQL的执行过程,直接使用:

jdbcTemplate.update("insert into user(name,age,sex)values(?,?,?)",

new Object[] { user.getName(), user.getAge(),user.getSex() },

new int[] { java.sql.Types.VARCHAR,java.sql.Types.INTEGER, java.sql.Types.VARCHAR });

SQL语句对应的参数,对应参数的类型清晰明了,这都归功于Spring为我们做了封装,而真正的JDBC调用其实非常繁琐,你需要这么做:

PreparedStatement updateSales = con.prepareStatement("insert into user(name,age, sex)values(?,?,?)");

updateSales.setString(1, user.getName());

updateSales.setInt(2, user.getAge());

updateSales.setString(3, user.getSex());

那么看看Spring是如何做到封装上面的操作呢?首先,所有的操作都是以pss.setValues(ps)为入口的。这个pss所代表的正式ArgumentTypePreparedStatementSetter。其中的setValues如下:

public void setValues(PreparedStatement ps) throws SQLException {      int parameterPosition = 1;      if (this.args != null) {          //遍历每个参数以作类型匹配及转换          for (int i = 0; i < this.args.length; i++) {              Object arg = this.args[i];              //如果是集合类则需要进入集合类内部递归解析集合内部属性              if (arg instanceof Collection && this.argTypes[i] != Types.ARRAY) {                  Collection entries = (Collection) arg;                  for (Object entry : entries) {                      if (entry instanceof Object[]) {                          Object[] valueArray = ((Object[]) entry);                          for (Object argValue : valueArray) {                              doSetValue(ps, parameterPosition, this.argTypes[i], argValue);                              parameterPosition++;                          }                      }                      else {                          doSetValue(ps, parameterPosition, this.argTypes[i], entry);                          parameterPosition++;                      }                  }              }              else {                  //解析当前属性                  doSetValue(ps, parameterPosition, this.argTypes[i], arg);                  parameterPosition++;              }          }      }  }

对单个参数及类型的匹配处理:

private static void setParameterValueInternal(PreparedStatement ps, int paramIndex, int sqlType,          String typeName, Integer scale, Object inValue) throws SQLException {        String typeNameToUse = typeName;      int sqlTypeToUse = sqlType;      Object inValueToUse = inValue;        // override type info?      if (inValue instanceof SqlParameterValue) {          SqlParameterValue parameterValue = (SqlParameterValue) inValue;          if (logger.isDebugEnabled()) {              logger.debug("Overriding type info with runtime info from SqlParameterValue: column index " + paramIndex +                      ", SQL type " + parameterValue.getSqlType() + ", type name " + parameterValue.getTypeName());          }          if (parameterValue.getSqlType() != SqlTypeValue.TYPE_UNKNOWN) {              sqlTypeToUse = parameterValue.getSqlType();          }          if (parameterValue.getTypeName() != null) {              typeNameToUse = parameterValue.getTypeName();          }          inValueToUse = parameterValue.getValue();      }        if (logger.isTraceEnabled()) {          logger.trace("Setting SQL statement parameter value: column index " + paramIndex +                  ", parameter value [" + inValueToUse +                  "], value class [" + (inValueToUse != null ? inValueToUse.getClass().getName() : "null") +                  "], SQL type " + (sqlTypeToUse == SqlTypeValue.TYPE_UNKNOWN ? "unknown" : Integer.toString(sqlTypeToUse)));      }        if (inValueToUse == null) {          setNull(ps, paramIndex, sqlTypeToUse, typeNameToUse);      }      else {          setValue(ps, paramIndex, sqlTypeToUse, typeNameToUse, scale, inValueToUse);      }  }

 

 

转载地址:http://qqumo.baihongyu.com/

你可能感兴趣的文章
snmp之——2交换机MIB库ID和物理端口不对应
查看>>
Centos6.7下安装python连接mysql环境故障解决
查看>>
12.交换路由密码恢复
查看>>
sudo:sorry,you must have a tty to run sudo
查看>>
python os模块
查看>>
服务器操作系统之Solaris架构攻略
查看>>
java——演示封装的思想
查看>>
直接使用提交过来的类来更新字段EntityState.Modified并过滤null值的方法
查看>>
美团在Redis上踩过的一些坑-5.redis cluster遇到的一些问题
查看>>
浅谈JAVA的线程安全与性能之间的权衡
查看>>
python入门系列之一:Centos6下python2.7的安装
查看>>
31.软连接
查看>>
oracle 11g 手工热备-数据库
查看>>
跟我一起数据挖掘(17)——分布式缓存
查看>>
python paramiko 执行命令
查看>>
centos7安装
查看>>
docker强制删除none的image镜像
查看>>
JavaScript学习
查看>>
Linux下通用二进制安装包安装MySQL-5.6.37
查看>>
简单跳板机的搭建笔记
查看>>