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<Integer>() {
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);
}
}

SpringJDBC解析3-回调函数(update为例)的更多相关文章

  1. glib简单记录包括字符串,主循环,回调函数和xml解析

    一.将最近用到的glib字符串功能整理了下直接用程序记录比较好看懂 #define MAX_LEN 100gchar * demo (char* msg, ...){    gchar * pcfgf ...

  2. C++ 回调函数的定义与用法

    一回调函数 我们经常在C++设计时通过使用回调函数可以使有些应用(如定时器事件回调处理.用回调函数记录某操作进度等)变得非常方便和符合逻辑,那么它的内在机制如何呢,怎么定义呢?它和其它函数(比如钩子函 ...

  3. C++回调函数的应用<转自:http://blog.csdn.net/wubin1124/article/details/4386269>

    一回调函数 我们经常在C++设计时通过使用回调函数可以使有些应用(如定时器事件回调处理.用回调函数记录某操作进度等)变得非常方便和符合逻辑,那么它的内在机制如何呢,怎么定义呢?它和其它函数(比如钩子函 ...

  4. python并发编程之多进程2-------------数据共享及进程池和回调函数

    一.数据共享 1.进程间的通信应该尽量避免共享数据的方式 2.进程间的数据是独立的,可以借助队列或管道实现通信,二者都是基于消息传递的. 虽然进程间数据独立,但可以用过Manager实现数据共享,事实 ...

  5. win32的回调函数

    [转]http://blog.csdn.net/w419675647/article/details/6599070 众所周知,win32的回调函数WndProc()是操作系统调用的函数,win32用 ...

  6. Windows编程中回调函数的使用心得(MFC篇)

    回调函数就是一个通过函数指针调用的函数.如果你把函数的指针(地址)作为参数传递给另一个函数,当这个指针被用来调用其所指向的函数时,我们就说这是回调函数.回调函数不是由该函数的实现方直接调用,而是在特定 ...

  7. python并发编程之多进程2-(数据共享及进程池和回调函数)

    一.数据共享 1.进程间的通信应该尽量避免共享数据的方式 2.进程间的数据是独立的,可以借助队列或管道实现通信,二者都是基于消息传递的. 虽然进程间数据独立,但可以用过Manager实现数据共享,事实 ...

  8. python并发编程之多进程2数据共享及进程池和回调函数

    一.数据共享 尽量避免共享数据的方式 可以借助队列或管道实现通信,二者都是基于消息传递的. 虽然进程间数据独立,但可以用过Manager实现数据共享,事实上Manager的功能远不止于此. 命令就是一 ...

  9. Python之网路编程之进程池及回调函数

    一.数据共享 1.进程间的通信应该尽量避免共享数据的方式 2.进程间的数据是独立的,可以借助队列或管道实现通信,二者都是基于消息传递的. 虽然进程间数据独立,但可以用过Manager实现数据共享,事实 ...

随机推荐

  1. mybatis新增数据后获取自增主键

    mybatis对应mysql <insert id="insert" parameterType="com.timestech.wsgk.web.model.Sys ...

  2. 转载jQuery图片放大插件[twiPicZoom]

    转载http://xuzhihong1987.blog.163.com/blog/static/26731587201312821725913/ 功能说明: 双击查看大图,鼠标滚动放大缩小,能够切换到 ...

  3. August 8th 2016, Week 33rd Monday

    Everything is going on, but don't give up trying. 万事随缘,但不要放弃努力. Every time when I want to give up, y ...

  4. !对c++类的理解

    c++的类可以分为两类,一种是entity的类(i.e.,实体类),一种是function的类(i.e.,功能类). 对于构造entity的类,包括这种entity的属性已经它本身具备的功能: 而fu ...

  5. python基础——高阶函数

    python基础——高阶函数 高阶函数英文叫Higher-order function.什么是高阶函数?我们以实际代码为例子,一步一步深入概念. 变量可以指向函数 以Python内置的求绝对值的函数a ...

  6. IOS常用正则表达式

    IOS常用正则表达式 正则表达式用于字符串处理.表单验证等场合,实用高效.现将一些常用的表达式收集于此,以备不时之需. 匹配中文字符的正则表达式: [\u4e00-\u9fa5] 评注:匹配中文还真是 ...

  7. MVC学习笔记--跟小静学MVC相关语法特性小补习

    http://www.cnblogs.com/janes/archive/2012/10/15/2721101.html http://www.cnblogs.com/h82258652/p/4795 ...

  8. CLR via C#(10)-参数

    一. 命名参数.可选参数 命名参数和可选参数是在Visual C#2010中引入的新特性. 笨地儿我个瓜不兮兮的,今天才知道. 可选参数:定义方法时为参数设置默认值,调用该方法时可以省略为某些形参指定 ...

  9. 与你相遇好幸运,CentOS 7 x86_64使用Yum安装PostgreSQL

    访问http://yum.pgrpms.org/reporpms/repoview/letter_p.group.html,下载并安装和当前系统对应的rpm文件. wget https://downl ...

  10. Java集合源码学习(五)几种常用集合类的比较

    这篇笔记对几个常用的集合实现,从效率,线程安全和应用场景进行综合比较. >>ArrayList.LinkedList与Vector的对比 (1)相同和不同都实现了List接口,使用类似.V ...