SpringJDBC解析3-回调函数(update为例)

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);  }  
}  

 

 

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/news/457545.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

System.InvalidOperationException : 不应有 Response xmlns=''。

xml如下&#xff1a; <?xml version"1.0" encoding"UTF-8"?> <Response version"2"><datacash_reference>4700203048783633</datacash_reference><information>Failed to identify the card scheme of the supp…

Navicat Premium连接SQL Server

Navicat Premium连接SQL Server 步骤&#xff1a; 激活SQL Server 服务配置SQL Server网络配置连接SQL Server 激活SQLServer服务 直接搜索 计算机管理 点 服务和应用程序&#xff0c; 点 SQL Server配置管理器&#xff0c; 双击第一个SQL Server服务 不出意外的话&#xf…

processon完全装逼指南

一、引言 作为一名IT从业者&#xff0c;不仅要有扎实的知识储备&#xff0c;出色的业务能力&#xff0c;还需要具备一定的软实力。软实力体现在具体事务的处理能力&#xff0c;包括沟通&#xff0c;协作&#xff0c;团队领导&#xff0c;问题的解决方案等&#xff0c;这些能力在…

解决svn log显示no author,no date的方法之一

只要把svnserve.conf中的anon-access read 的read 改为none&#xff0c;也不需要重启svnserve就行 sh-4.1# grep "none" /var/www/html/svn/pro/conf/svnserve.conf ### and "none". The sample settings below are the defaults. anon-access none转载…

解决larave-dompdf中文字体显示问题

0、使用MPDF dompdf个人感觉没有那么好用&#xff0c;最终的生产环境使用的是MPDF&#xff0c;github上有文档说明。如果你坚持使用&#xff0c;下面是解决办法。可以明确的说&#xff0c;中文乱码是可以解决的。 1、安装laravel-dompdf依赖。 Packagist&#xff1a;https://pa…

mfc程序转化为qt_小峰的QT学习笔记

我的专业是输电线路&#xff0c;上个学期&#xff0c;我们开了一门架空线路设计基础的课&#xff0c;当时有一个大作业是计算线路的比载&#xff0c;临界档距&#xff0c;弧垂最低点和安装曲线。恰逢一门结课考试结束&#xff0c;大作业ddl快到&#xff0c;我和另外两个同专业的…

【IDEA 2016】intellij idea tomcat jsp 热部署

刚开始用IDEA&#xff0c;落伍的我&#xff0c;只是觉得IDEA好看。可以换界面。想法如此的low。 真是不太会用啊&#xff0c;弄好了tomcat。程序启动竟然改动一下就要重启&#xff0c;JSP页面也一样。 IDEA可以配置热部署&#xff0c;打开tomcat配置页面&#xff0c;将红框处&a…

设计模式11---组合模式(Composite Pattern)

一、组合模式定义 将对象组合成树形结构以表示“部分-整体”的层次结构&#xff0c;使得用户对单个对象和组合对象的使用具有一致性。Compose objects into tree structures to represent part-whole hierarchies. Composite lets clients treat individual objects and compos…

python实现Redis订阅发布

Redis 发布订阅 Redis 发布订阅可以用在像消息通知&#xff0c;群聊&#xff0c;定向推送&#xff0c;参数刷新加载等业务场景 发布订阅模型有三个角色&#xff1a; 发布者&#xff08;Publisher&#xff09;订阅者(Subscriber)频道(channel) 每个订阅者可以订阅多个频道&am…

iOS开发UI篇—xib的简单使用

一、简单介绍 xib和storyboard的比较&#xff0c;一个轻量级一个重量级。 共同点&#xff1a; 都用来描述软件界面 都用Interface Builder工具来编辑 不同点: Xib是轻量级的&#xff0c;用来描述局部的UI界面 Storyboard是重量级的&#xff0c;用来描述整个软件的多个界面&…

【云栖计算之旅】线下沙龙第2期精彩预告:Docker在云平台上的最佳实践

Docker是一个开源的应用容器引擎&#xff0c;提供了一种在安全、可重复的环境中自动部署软件的方式&#xff0c;允许开发者将他们的应用和依赖包打包到一个可移植的容器中&#xff0c;然后发布到任何流行的Linux机器上&#xff0c;也可以实现虚拟化。容器完全使用沙箱机制&…

mysql int类型的长度值

整数类型的存储和范围(来自mysql手册) 类型字节最小值最大值(带符号的/无符号的)(带符号的/无符号的)TINYINT1-1281270255SMALLINT2-3276832767065535MEDIUMINT3-83886088388607016777215INT4-2147483648214748364704294967295BIGINT8-92233720368547758089223372036854775807…

龙王我当定了(一个在QQ刷龙王的脚本)

自从学了python&#xff0c;龙王再也没丢过&#xff0c;就是经常被打, QQ 和 TIM 都可以&#xff0c;发送时要把聊天窗口打开。 # 如果import报错&#xff0c;那可以pip下载这几个模块试一试 import win32gui import win32con import win32clipboard as w import random from…

navicat for mysql 数据库备份与还原

一, 首先设置, 备份保存路径 工具 -> 选项 点开 其他 -> 日志文件保存路径 二. 开始备份 备份分两种, 一种是以sql保存, 一种是保存为备份 SQL保存 右键点击你要备份的数据库, -> 转储SQL文件 选择位置和文件名 开始转储 导入 建议 删除所有表 或 重新建数据库 同导出…

DES的原理及python实现

DES加密算法原理及实现 DES是一种对称加密算法【即发送者与接收者持有相同的密钥】&#xff0c;它的基本原理是将要加密的数据划分为n个64位的块&#xff0c;然后使用一个56位的密钥逐个加密每一个64位的块&#xff0c;得到n个64位的密文块&#xff0c;最后将密文块拼接起来得…

华为手机充满有提醒吗_2020手机充电速度排名:最快21分钟充满,华为第15名

5G手机扎堆出现&#xff0c;中国5G基站数量也是不断增多&#xff0c;中国移动曾经表态&#xff0c;2020年底将会在全国地级市覆盖5G网络&#xff0c;全民5G时代终于到来&#xff01;从目前国内手机出货量数据来看&#xff0c;5G手机占比已经达到了六成以上&#xff0c;国产5G手…

关于移动手机端富文本编辑器qeditor图片上传改造

日前项目需要在移动端增加富文本编辑&#xff0c;上网找了下&#xff0c;大多数都是针对pc版的&#xff0c;不太兼容手机&#xff0c;当然由于手机屏幕小等原因也限制富文本编辑器的众多强大功能&#xff0c;所以要找的编辑器功能必须是精简的。 找了好久&#xff0c;发现qedit…

Java IO 系统

Java IO系统 File类 用来处理文件目录&#xff0c;既可以代表一个特定文件的名称&#xff0c;也可以代表一组文件的名称&#xff0c;如果代表的是一个文件组&#xff0c;可以调用File.list()方法返回一个字符数组。 list()不传递任何参数时返回该目录下所有文件或文件名的字…

javascript/jquery高度宽度详情解说分析

为什么80%的码农都做不了架构师&#xff1f;>>> 一、window对象表示浏览器中打开的窗口 二、window对象可以省略 一、document对象是window对象的一部分 二、浏览器的HTML文档成为Document对象 window.location和document.location window对象的location属性引用的…

红黑树插入时的自平衡

红黑树插入时的自平衡 红黑树实质上是一棵自平衡的二叉查找树&#xff0c;引入带颜色的节点也是为了方便在进行插入或删除操作时&#xff0c;如果破坏了二叉查找树的平衡性能通过一系列变换保持平衡。 红黑树的性质 每个节点要么是红色&#xff0c;要么是黑色根节点必须是黑…