文档章节

Spring&JDBC杂谈

cwalet
 cwalet
发布于 2012/07/13 11:13
字数 1800
阅读 661
收藏 5
点赞 0
评论 3

下面的问题都是从以下代码引申而来:

this.simpleJdbcOperation.getJdbcOperations().update(new PreparedStatementCreator() {

	@Override
	public PreparedStatement createPreparedStatement(Connection conn) throws SQLException {
		sql = "DELETE FROM A a WHERE a.name=:name AND a.time=:time";// PreparedStatement不支持占位符格式
		PreparedStatement ps = conn.prepareStatement(sql, PreparedStatement.RETURN_GENERATED_KEYS);// 返回id
		ps.setObject(1, obj.getName());// 可能为空的对象使用setObject
		if (null != obj.getDate())
			ps.setDate(4, new Date(obj.getDate().getTime()));
		else
			ps.setNull(4, Types.DATE);// 为空的对象使用setNull
		return ps;
	}

}, keyHolder);


一、SimpleJdbcTemplateNamedParameterJdbcTemplateJdbcTemplate 这三者的区别

参考:Spring Framework reference 2.0.5 参考手册中文版

SimpleJdbcOperations其实是包含Jdk5.0新特性的NamedParameterJdbcTemplate和JdbcTemplate的集合,

它的多数实现都是由NamedParameterJdbcTemplate完成的,并且有方法获取其他两个JdbcTemplate的实例, 推荐使用!

(在张培立同学的提醒(见评论)下,发现2.5中SimpleJdbcOperations也已经被标注为了@Deprecated,大概是作者更喜欢其他两个JdbcTemplate,而且也实现了SimpleJdbcOperations的所有功能,因此还是推荐使用NamedParameterJdbcTemplate和JdbcTemplate)

SimpleJdbcTemplate类是JdbcTemplate类的一个包装器(wrapper),它利用了Java 5的一些语言特性,比如Varargs和Autoboxing。对那些用惯了Java 5的程序员,这些新的语言特性还是很好用的。

另外说说NamedParameterJdbcTemplate,同时也回答我的第一个问题:JDBC不支持命名参数的占位符吗(如:name)?

自从使用了ORM或其他框架后,就很少直接接触JDBC API了,习惯了Spring封装的Template、ibatis、JPA的JPQL等这些支持参数占位符的写法,

其实JDBC中的SQL写法是不支持命名参数占位符

NamedParameterJdbcTemplate类增加了在SQL语句中使用命名参数的支持。在此之前,在传统的SQL语句中,参数都是用'?'占位符来表示的。 NamedParameterJdbcTemplate类内部封装了一个普通的JdbcTemplate,并作为其代理来完成大部分工作。

NamedParameterJdbcTemplate中有一个工具类专门用于命名参数SQL的解析和还原:

NamedParameterUtils.parseSqlStatement(sql);

因此, NamedParameterJdbcTemplate是JdbcTemplate的升级版,而SimpleJdbcTemplate则是最高级的版本!

关于SimpleJdbcTemplate的用法参见:使用Spring的NamedParameterJdbcTemplate完成DAO操作


二、关于 setObject 与 setNull

Jdbc中的PreparedStatement对象包含了众多的setXXX方法,用于对SQL语句中“?”对应的字段赋值。

通过查看MySQL驱动中的实现可知,使用setObject是一种最懒同时也是最保险的方法,它会自动去判断是否是常用数据类型并做相应处理,

因为几乎每一个setXXX方法中都有对空的判断,对于空值选择使用setNull方法。

可能为空的对象使用setObject但并不是为空(指为NULL)的对象就必须使用setObject才能正确赋值

说道setNull,实际上也是设定一个“null”的字符串来替代,其实这个方法对于接口使用者来说是基本无用的,可以作为protect方法不理。

因此,当你不确定你的程序里接受的是什么类型的值时,使用setObject吧,有益无害!


三、能否通过KeyHolder来获取一条删除语句的id?

想想就觉得不可能的。可以使用KeyHolder来获取新插入数据自动生成的ID,但有时候删除某条数据(通过其他字段删除,而非主键ID),

我们也希望能直接返回ID,而无需先去查询一次数据库。但这实际上是不行的。

在JDBC中通常以下面的方式获取新生成的ID:

PreparedStatement ps = connection.prepareStatement(
"insert into article(content,title) values('a','b')", Statement.RETURN_GENERATED_KEYS);
ps.executeUpdate();
ResultSet rs = ps.getGeneratedKeys();
rs.first();
System.out.println(rs.getString(1));

Spring将getGeneratedKeys()的操作封装到一个KeyHolder对象中,查看了一下源码,

实际上还是通过“SELECT LAST_INSERT_ID()”的方式来获取IDENTITY的ID,com.mysql.jdbc.StatementImpl.getLastInsertID()

This gets around the un-threadsafe behavior of "select LAST_INSERT_ID()" which is tied to the Connection that created this Statement, and therefore could have had many INSERTS performed before one gets a chance to call "select LAST_INSERT_ID()".

 这里列举了三种获取自增长主键的方法:MySQL中关于自增长主键的获取,其中第2点说的比较清楚:

(2)LAST_INSERT_ID: LAST_INSERT_ID 是与table无关的,如果向表a插入数据后,再向表b插入数据,LAST_INSERT_ID会改变。 在多用户交替插入数据的情况下max(id)显然不能用。 这就该使用LAST_INSERT_ID了,因为LAST_INSERT_ID是基于Connection的,只要每个线程都使用独立的Connection对象,LAST_INSERT_ID函数将返回该Connection对AUTO_INCREMENT列最新的insert or update*作生成的第一个record的ID。这个值不能被其它客户端(Connection)影响,保证了你能够找回自己的 ID 而不用担心其它客户端的活动,而且不需要加锁。使用单INSERT语句插入多条记录, LAST_INSERT_ID返回一个列表。

对于多列插入的LAST_INSERT_ID()返回的结果将只有第一个。具体见MySQL文档: 信息函数


四、关于Spring配置文件的bean标签中的id和name的区别

谈谈Spring配置中<bean>的id和name属性的花拳秀腿,以下引用自CSDN上的讨论:http://sina.lt/dkX

1.id是唯一的,name可以指定多个,其他的就是别名,例如 <bean name= "A1,A2 ".../> A2就是别名
2.XML规范严格限定了在XML ID中合法的字符。例如在spring mvc中我们如果使用UrlFilenameViewController:   <bean name= "/index.htm " class= "org.springframework.web.servlet.mvc.UrlFilenameViewController "/> 那么只能用name,因为XML规范中ID不能含有“/ "之类的字符。
3.如果被引用的bean在同一个xml文件中而且bean的名称是bean的 id,那么就可以使用local属性.这 个是spring参考文档里面的,注意看看。


五、传说中的JDBC4

很久以前听说JDK6中会发布JDBC4,这里是它的新特性,但直到今天依然没有看到这一成果。

莫须有,JDBC4最终版并没有加入该功能。也许演变成了现在的spring-data-jdbc,以及JPA的部分特性。

JDBC4新特性之自动加载驱动:

Applications no longer need to explictly load JDBC drivers using Class.forName(). Existing programs which currently load JDBC drivers using Class.forName() will continue to work without modification.

也许你没有意识到,但是现在你确实无需写Class.forName...(已有程序自然也不会受影响)

When the method getConnection is called, the DriverManager will attempt to locate a suitable driver from amongst those loaded at initialization and those loaded explicitly using the same classloader as the current applet or application.

调用getConnection方法时,驱动管理器会尝试去定位一个合适的驱动。(驱动类必须放在Classpath里,否则,谁知道驱动在哪儿?)

  • 既然避免了手动加载驱动类,JVM是如何主动发现它的呢?

参考:http://docs.oracle.com/javase/6/docs/api/java/sql/DriverManager.html

The DriverManager methods getConnection and getDrivers have been enhanced to support the Java Standard Edition Service Provider mechanism. JDBC 4.0 Drivers must include the file META-INF/services/java.sql.Driver. This file contains the name of the JDBC drivers implementation of java.sql.Driver. For example, to load the my.sql.Driver class, the META-INF/services/java.sql.Driver file would contain the entry: my.sql.Driver

DriverManagergetConnectiongetDrivers方法都被增强了,提供了所谓的Java标准服务提供机制,

因此实现JDBC4的驱动必须将实际的驱动类名写入到文件META-INF/services/java.sql.Driver中。

© 著作权归作者所有

共有 人打赏支持
cwalet
粉丝 43
博文 110
码字总数 86709
作品 0
其他
加载中

评论(3)

zplswf
zplswf

引用来自“cwalet”的评论

引用来自“张培立”的评论

3.1版本的 SimpleJdbcTemplate不过现在已经禁用了

为什么呢?还是有新的替代?现在用的是2.5

现在高版本的 用的是要么jdbctempate 要么是NamedParameterJdbcTemplate
cwalet
cwalet

引用来自“张培立”的评论

3.1版本的 SimpleJdbcTemplate不过现在已经禁用了

为什么呢?还是有新的替代?现在用的是2.5
zplswf
zplswf
3.1版本的 SimpleJdbcTemplate不过现在已经禁用了
杂谈nginx 301 重定向在非常规破解中的利用

杂谈nginx 301 重定向在非常规破解中的利用 火星信息安全研究院2017-12-281 阅读 Python 在某些特定的情况下,如果软件采用本地加服务器校验的方式进行注册时候。单纯的本地破解可能很快就是...

火星信息安全研究院
2017/12/28
0
0
好书推荐.Philosophy.>

图书封面: 书籍简介: 主要讲述了作者在该作品中倾注了其对中国民众的关注,以反讽和幽默的手法直面生活,从一个轻松的角度来解析身边复杂的事态. 书籍目录: 第 001 章 沉默的大多数 第 002 章 ...

满满李
2016/05/07
152
0
我的友情链接

51CTO博客开发 王春海的博客 桌面虚拟化杂谈 ZJS的微软桌面虚拟化 让"云"无处不在 欢迎光临ciywind博客 snowyan welcome! 海狗哥的流媒体空间 叔宝(孙亮) 下里巴人的家...

abchw
2017/11/22
0
0
【目录】姜晔的技术空间目录

逆向工程系列 逆向工程第001篇:解锁FIFA07传奇模式 逆向工程第002篇:打造自己的仙剑奇侠 逆向工程第003篇:跨越CM4验证机制的鸿沟(上) 逆向工程第004篇:跨越CM4验证机制的鸿沟(中) 逆...

ioio_jy
2014/09/15
0
0
我的友情链接

51CTO博客开发 兔样兔森破 王春海的博客 性能测试 Jack zhai 三角阳台的技术笔记本 虚拟化桌面支持 黄锦辉专栏 Citrix、网络工程师 桌面虚拟化杂谈 About:Blank H4cking 月缺 未暖 飞翔的猪 ...

yuanwx0328
2017/11/22
0
0
我的友情链接

王伟 积小流,成江海 马哥Linux培训 学神IT教育-讲师MK 系统网站运维 一盏烛光 一壶浊酒 运维自动化 运维杂谈Q群:223843163 技术成就梦想 峰云,就她了。 爱维Linux sery 李振良的技术博客...

swallow_zys
2017/11/22
0
0
解读:全球云服务商 IP 地址分析报告 2H 2017

分析报告如下: ▼ 来源:老高互联网杂谈 ↓↓↓ 点击"阅读原文" 【加入云技术社区】 相关阅读: 高端私有云项目交流群,欢迎加入! 基于Kubernetes和Docker构建微服务之路 2017年云市场十大...

云技术实践
02/01
0
0
我的友情链接

科来网络分析论坛 中华演讲网 人人网 音乐887 新东方 张琦 吴晓波 Helpdesk Log 张亚勤的博客 Jack zhai simeon技术专栏 培训小说 网管小王 童继龙谈信息化 郎咸平 不胜人生一场醉 王春海的博...

cf123456
2017/11/22
0
0
我的友情链接

51CTO博客开发 活不明白的博客--技术用时方觉少 网管小王 seven 老男孩的linux博客 技术成就梦想 转身离开-王军 斩月 林肯 吟—技术交流 桌面虚拟化杂谈 游造技术博客 暗黑魔君腾云端...

初级泥水工
2017/11/22
0
0
我的友情链接

老男孩linux培训 系统网络运维 千山岛主之微软技术空间站 张书兴 曾垂鑫的技术专栏 孙亮的IT运维技术 Chocolee Tonyguo De博客【知识改变命运,技术成就梦想】 马哥Linux培训 lzy821218 风之...

sandshell
2017/11/22
0
0

没有更多内容

加载失败,请刷新页面

加载更多

下一页

Android 复制和粘贴功能

做了一回搬运工,原文地址:https://blog.csdn.net/kennethyo/article/details/76602765 Android 复制和粘贴功能,需要调用系统服务ClipboardManager来实现。 ClipboardManager mClipboardM...

她叫我小渝
29分钟前
0
0
拦截SQLSERVER的SSL加密通道替换传输过程中的用户名密码实现运维审计(一)

工作准备 •一台SQLSERVER 2005/SQLSERVER 2008服务 •SQLSERVER jdbc驱动程序 •Java开发环境eclipse + jdk1.8 •java反编译工具JD-Core 反编译JDBC分析SQLSERVER客户端与服务器通信原理 SQ...

紅顏為君笑
46分钟前
4
0
jQuery零基础入门——(六)修改DOM结构

《jQuery零基础入门》系列博文是在廖雪峰老师的博文基础上,可能补充了个人的理解和日常遇到的点,用我的理解表述出来,主干出处来自廖雪峰老师的技术分享。 在《零基础入门JavaScript》的时...

JandenMa
今天
0
0
linux mint 1.9 qq 安装

转: https://www.jianshu.com/p/cdc3d03c144d 1. 下载 qq 轻聊版,可在百度搜索后下载 QQ7.9Light.exe 2. 去wine的官网(https://wiki.winehq.org/Ubuntu) 安装 wine . 提醒网页可以切换成中...

Canaan_
今天
0
0
PHP后台运行命令并管理运行程序

php后台运行命令并管理后台运行程序 class ProcessModel{ private $pid; private $command; private $resultToFile = ''; public function __construct($cl=false){......

colin_86
今天
1
0
数据结构与算法4

在此程序中,HighArray类中的find()方法用数据项的值作为参数传递,它的返回值决定是否找到此数据项。 insert()方法向数组下一个空位置放置一个新的数据项。一个名为nElems的字段跟踪记录着...

沉迷于编程的小菜菜
今天
1
1
fiddler安装和基本使用以及代理设置

项目需求 由于开发过程中客户端和服务器数据交互非常频繁,有时候服务端需要知道客户端调用接口传了哪些参数过来,这个时候就需要一个工具可以监听这些接口请求参数,已经接口的响应的数据,这种...

银装素裹
今天
0
0
Python分析《我不是药神》豆瓣评论

读取 Mongo 中的短评数据,进行中文分词 对分词结果取 Top50 生成词云 生成词云效果 看来网上关于 我不是药神 vs 达拉斯 的争论很热啊。关于词频统计就这些,代码中也会完成一些其它的分析任...

猫咪编程
今天
0
0
虚拟机怎么安装vmware tools

https://blog.csdn.net/tjcwt2011/article/details/72638977

AndyZhouX
昨天
1
0
There is no session with id[xxx]

参考网页 https://blog.csdn.net/caimengyuan/article/details/52526765 报错 2018-07-19 23:04:35,330 [http-nio-1008-exec-8] DEBUG [org.apache.shiro.web.servlet.SimpleCookie] - Found......

karma123
昨天
0
0

没有更多内容

加载失败,请刷新页面

加载更多

下一页

返回顶部
顶部