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. C++与C#对比学习:类初始化

    类和柏拉图的理念世界 我们知道面向对象编程中到处是一个个的类,但类只是个概念性的东西,不是个实体,不占内存,你没实例化之前也不能用它.只有把类实例化成一个对象后,它才是一个真正存在的实体.占有内存,能 ...

  2. xcode7 免费真机调试

    原文链接:http://www.cnblogs.com/tandaxia/p/4839997.html 刚新安装了Xcode7 Version 7.1 beta , 据说这个版本可以免费真机调试,于是 ...

  3. 甲鱼od19篇随笔

    在一个程序里会有多个对话框,这时要准确的判断要找的对话框就比较困难了所以这里就需要借助 1:Resource Hacker工具来准确的定位涉及到的对话框 2:在od中查找指令,然后在所有找到的指令上下 ...

  4. osgconv 将多个模型合成一个模型

    osgconv a.osg b.osg c.osg BigOne.ive 以上命令的作用是将a.osg.b.osg.c.osg三个模型合并到BigOne.ive模型

  5. MyEclipse8.5破解方法

    本文是转自其它博文,用以留着备份的~ Step: 1.建立一个任意名称的Java Project 2.在该工程中建立一个名文MyEclipseGen的Java文件(MyEclipseGen.java) ...

  6. WEB前端开发学习:源码canvas 雪

    WEB前端开发学习:源码canvas 雪 双旦节要到了,程序员们为了响应气氛,特别用代码制作了动态雪花,WEB前端开发学习的初学者们一起跟着案例做一遍吧! <!DOCTYPE html> ...

  7. URL重写

    http://localhost:37977/UrlWrite.ashx?id=9URL重写成下面的访问方式,有利于SEO搜索引擎http://localhost:37977/UrlWrite-8.a ...

  8. Android 实现类似微信客户端朋友圈更新提示的小红点&栏目订阅

    用到的类: com.jauker.widget.BadgeView 实现代码: BadgeView imageBadge = new BadgeView(getContext()); imageBad ...

  9. DB2应用中嵌入式SQL取值入本地变量

    Declare section for host variables in C and C++ embedded SQL applications You must use an SQL declar ...

  10. 数据结构和算法 – 11.高级排序算法(下)

    三.选择类排序 3.1.简单选择排序 http://www.cnblogs.com/tangge/p/5338734.html#XuanZe 3.2 堆排序 要知道堆排序,首先要了解一下二叉树的模型. ...