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. MST:Agri-Net(POJ 1258)

     Agri-Net 题目大意:农夫有一片农场,现在他要把这些田地用管子连起来,田地之间有一定距离,铺设每一段管子的长度与这些田地与田地距离是一样的,问你最小的铺设方案. 这一题很裸,Kruskal算法 ...

  2. Xcode无法启动ios模拟器的问题

    一.问题描述 开发过程需要来回切换ios模拟器调试程序,开始在iPhone 4s下调试,然后切换到iPhone 6s Plus,再切换回iPhone 4s,遇到无法启动ios模拟器.错误提示如下: 二 ...

  3. codeforces 515A.Drazil and Date 解题报告

    题目链接:http://codeforces.com/problemset/problem/515/A 题目意思:问能否从 (0, 0) 出发,恰好走 s 步,到达该位置(a, b). 首先容易知道, ...

  4. August 15th 2016 Week 34th Monday

    Why not discovering as there is glorious faraway scenery? 远方有诗篇,何不去发现? An advertisement of Land Rove ...

  5. 升级CUDA版本导致VS2010错误:未找到导入的项目XXX,请确认<Import>声明中的路径正确,且磁盘上存在该文件

    转自:http://www.cnblogs.com/yeahgis/p/3853420.html VS2010错误:未找到导入的项目XXX,请确认<Import>声明中的路径正确,且磁盘上 ...

  6. 第三章 C#循环与方法

    第一节1-For循环入门 语法: for(条件表达式) { 执行语句 } 练习: 第三章作业1.写一个程序打印100到200的值;2.写一个程序从10打印到1:3.写一个程序打印10到30之间的所有偶 ...

  7. JS返回上一页

    <button  onclick="javascript:history.go(-1);">返回上一页</button> <button  oncli ...

  8. 20145206邹京儒《Java程序设计》第6周学习总结

    20145206 <Java程序设计>第6周学习总结 教材学习内容总结 第十章 输入/输出 Java将输入/输出抽象化为串流,数据有来源及目的地,衔接两者的是串流对象. 从应用程序角度来看 ...

  9. JS window.open()属性

    一. Window 对象 Window 对象是 JavaScript 层级中的顶层对象. Window 对象代表一个浏览器窗口或一个框架. Window 对象会在 <body> 或 < ...

  10. Android Message Handling Mechanism

    转自:http://solarex.github.io/blog/2015/09/22/android-message-handling-mechanism/ Android is a message ...