文档章节

Spring&JDBC杂谈

cwalet
 cwalet
发布于 2012/07/13 11:13
字数 1800
阅读 712
收藏 5

精选30+云产品,助力企业轻松上云!>>>

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

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
粉丝 44
博文 111
码字总数 87663
作品 0
其他
私信 提问
加载中
此博客有 3 条评论,请先登录后再查看。
词语搜索算法思想 - 第一步 问题描述

问题描述: 天涯社区,版块众多,怎样能让用户快速找到自己想要去的版块? 传统方式,分组、分类、导航形式。这种方式,用户找到自己想要去的版块还是非常麻烦。 一个快速版块名称搜索将会给...

方旭
2012/02/24
320
0
向顶尖高手学习技巧,方法,认知,成长路径

向顶尖高手学习技巧,方法,认知,成长路径 顶尖高手的成功不可复制只能学习,每天都比前一天进步,每日精进 越难的事情越要早做、久做、不停的做 从提高自己的不可替代性开始,专注做到极致...

osc_t1i6yzae
2018/11/12
6
0
词语搜索算法思想 - 第二步 算法思想

接下来我们来分析这个问题,解决这个问题最核心的思想是,我们要准备一个用户输入的字符和版块对应结构: key=“天”,value=[“情感天地”、“天涯杂谈”] key=“娱乐”, value=[ “娱乐八...

方旭
2012/02/24
304
0
杂谈nginx 301 重定向在非常规破解中的利用

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

火星信息安全研究院
2017/12/28
0
0
悠然乱弹:软件开发杂谈

杂谈之一:技术只是成功的一点点基础条件,真正还是得靠做人 话说,有位lianzi同学,水平不错,思想超前,签约阿里现在在百度实习,以前因为喷我的贴又没有啥理由,因此告诉他离我远一点,但...

悠悠然然
2014/11/10
1.3K
11

没有更多内容

加载失败,请刷新页面

加载更多

主机“ xxx.xx.xxx.xxx”不允许连接到该MySQL服务器

问题: This should be dead simple, but I cannot get it to work for the life of me. 这本来应该很简单,但是我无法让它在我的一生中发挥作用。 I'm just trying to connect remotely to......

技术盛宴
今天
14
0
Cocoa Autolayout:内容拥抱与内容压缩阻力优先

问题: I can't find a clear answer on Apple documentation regarding Cocoa Autolayout about the difference between content hugging and compression resistance. 关于Cocoa Autolayou......

javail
今天
24
0
OSChina 周二乱弹 —— 附近居民接连失踪,你们有什么头绪吗

Osc乱弹歌单(2020)请戳(这里) 【今日歌曲】 @薛定谔的兄弟 :分享洛神有语创建的歌单「我喜欢的音乐」: 《伤离别(原版)》- 黄霑 手机党少年们想听歌,请使劲儿戳(这里) @巴拉迪维 :睡...

小小编辑
今天
44
1
IntelliJ IDEA 默认快捷键大全

Remember these Shortcuts 常用 功能 快捷键 备注 ● Smart code completion Ctrl + Shift + Space - ● Search everywhere Double Shift - ● Show intention actions and quick-fixes Alt......

巨輪
今天
30
0
Hacker News 简讯 2020-07-14

更新时间: 2020-07-14 04:01 Bitcoin is more like ham radio than the early internet - (jpkoning.blogspot.com) 比特币更像是火腿收音机,而不是早期的互联网 得分:159 | 评论:140 Chipma......

FalconChen
今天
136
0

没有更多内容

加载失败,请刷新页面

加载更多

返回顶部
顶部