网络编程
位置:首页>> 网络编程>> 数据库>> 在Spring中用select last_insert_id()时遇到问题(2)

在Spring中用select last_insert_id()时遇到问题(2)

 来源:asp之家 发布时间:2009-05-24 19:50:00 

标签:Spring,select,主键,问题

应用层产生主键

Spring JDBC提供了自增键以及行集的支持,自增键对象让我们可以不依赖数据库的自增键,在应用层为新记录提供主键值。在JDK 1.4中引入了RowSet,它允许在连接断开的情况下操作数据,在这节里,我们将介绍如何在Spring JDBC中使用RowSet。

自增键的使用

一般数据库都提供了自增键的功能,如MySql的auto_increment、SqlServerr的identity字段等。Spring允许你在应用层产生主键值,为此定义了 org.springframework.jdbc.support.incrementer.DataFieldMaxValueIncrementer 接口,提供两种产生主键的方案:第一,通过序列产生主键;第二,通过表产生主键。根据主键产生方式和数据库的不同,Spring提供了若干实现类,如图 1所示:

图 1 DateFieldValueIncrementer继承类图

根据不同的主键产生方式,可能需要配置表名、主键字段名或序列名等信息。下面,我们以Oracle和MySql为例分别讲解使用序列及表字段产生主键值的方式。

DataFieldMaxValueIncrementer接口定义了3个获取下一个主键值的方法:
 int nextIntValue():获取下一个主键值,主键数据类型为int;
 long nextLongValue():获取下一个主键值,主键数据类型为long;
 String nextStringValue():获取下一个主键值,主键数据类型为String;

在其抽象实现类AbstractDataFieldMaxValueIncrementer中,提供了几个重要的属性,其中 incrementerName定义序列或主键表的名称;如果返回的主键是String类型,则paddingLength属性可能会派上用场,它允许你指定返回主键的长度,不足的部分前面补0。
HsqlMaxValueIncrementer和MySQLMaxValueIncrementer两个主键值产生器基于表进行工作。通过 columnName属性定义主键列的名字,通过cacheSize属性定义缓存的主键个数,当内存中的主键值用完后,产生器将一次性获取 cacheSize个主键,这样可以减少数据访问的次数,提高应用的性能。

我们通过DateFieldValueIncrementer从数据库中获取主键值来弥补这个缺陷。首先,调整PostJdbcDao的代码,添加DateFieldValueIncrementer属性,并通过它从序列中得到下一个主键值:

代码清单 13 使用DateFieldValueIncrementer产生主键

public class PostJdbcDao extends JdbcDaoSupport implements PostDao { private DataFieldMaxValueIncrementer incre; ①主键值产生器 public void addPost(final Post post) { … getJdbcTemplate().execute( sql,new AbstractLobCreatingPreparedStatementCallback( this.lobHandler) { protected void setValues(PreparedStatement ps, LobCreator lobCreator) throws SQLException { ps.setInt(1, incre.nextIntValue());②获取下一个主键值 … } }); } …//省略get/setter方法 }

在②处,我们通过incre.nextIntValue()获取下一个主键值。

以序列方式产生主键值

在Oracle数据库中创建一个seq_post_id序列,使用这个序列为t_post提供主键值,以下是创建seq_post_id的脚本: 

create sequence seq_post_id increment by 1start with 1;

接着,调整Spring的配置,使用OracleSequenceMaxValueIncrementer作为主键产生器:
<bean id="incre" class="org.springframework.jdbc.support.incrementer.OracleSequenceMaxValueIncrementer"><property name="incrementerName" value="seq_post_id"/> ①指定序列名 <property name="dataSource" ref="dataSource"/> ②设置数据源 </bean><bean id="postDao" parent="dao" class="com.baobaotao.dao.jdbc.PostJdbcDao"><property name="lobHandler" ref="oracleLobHandler"/><property name="incre" ref="incre"/> ③添加主键主键产生器 </bean>

以表方式产生主键值
在Mysql中创建一张用于维护t_post主键的t_post_id表,以下是创建该表及插入初始化的SQL脚本:

create table t_post_id(sequence_id int) type = MYISAM;
insert into t_post_id values(0);

由于主键维护表的并发访问量很大,所以最好将其声明为MYISAM类型,此外需要为该表提供初始值,以便后续主键值在此之上进行递增。
调整为MySql数据库后,我们仅需要对Spring配置进行小小的调整就可以了:

<bean id="incre"class="org.springframework.jdbc.support.incrementer.MySQLMaxValueIncrementer"><property name="incrementerName" value="t_post_id"/> ①设置维护主键的表名 <property name="columnName" value="sequence_id"/>②用于生成主键值的列名 <property name="cacheSize" value="10"/> ③缓存大小 <property name="dataSource" ref="dataSource"/></bean><bean id="postDao" parent="dao" class="com.baobaotao.dao.jdbc.PostJdbcDao"><property name="lobHandler" ref="defaultLobHandler"/><property name="incre" ref="incre"/></bean>

incrementerName和columnName都很容易理解,cacheSize决定一次返回的主键个数,这里我们设置为10。当第一次通过 MySQLMaxValueIncrementer# nextIntValue()获取主键值时,MySQLMaxValueIncrementer将使t_post_id. sequence_id递增10,而后续9次调用nextIntValue()方法时,都从缓存中获取主键值。直到第10次再次调用 nextIntValue()方法时,才会再次将t_post_id. sequence_id字段值递增10,如此循环反复。

小结

主键的生产方式从产生地点上可以分为应用层产生和数据库产生两种方式。应用层借助数据库的序列或表产生主键,这种方式可以保证程序的可移植性和安全性,同时可以通过缓存机制提高运行效率。有些数据库支持数据表自增键的主键产生机制,在JDBC 3.0以前的版本中,无法通过Statement自动获取新增记录的对应主键。这时需要在插入数据后,马上执行一条数据库相关的主键获取SQL语句以得到对应的主键值,在数据库高并发的情况下,有可能获取到不正确的主键值。在这种情况下,在插入数据前事先在应用层准备好主键值是很好的备选方案。

另外补充一点在SqlUpdate执行update之前需设置setReturnGeneratedKeys(true);

0
投稿

猜你喜欢

  • 对象Javascript 根本上是和对象相关的。数组是对象。函数是对象。对象是对象。那什么是对象呢?对象是名-值对的集合。名是字符串,值可以
  • 运行环境:IIS脚本语言:VBScript数据库:Access/SQL Server数据库语言:SQL1.概要:不论是在论坛,还是新闻系统,
  • 有两张表a表id val 1 a 2 b 3 c 4 d 5 e b表 a_id val 1 null 2 null 3 null 4 nu
  • 内容摘要:网页设计师制作网页最常用的设计软件应该就算adobe的产品Photoshop了,当然Photoshop不仅可以设计网页,不过作为网
  • 本XML系列教程将分三部分发布,到最后一期我们将拥有一个功能全面,更加友好的XML菜单。本教程这个第一期涉及到了一些XML的基础知识。大家都
  • Office家族成员中,人们对于Access 2000的了解,往往只局限在它的操作界面中,对于数据库管理的功能仍只是停留在建立表、数据输入、
  • 啥都不说了,直接奉献原代码 代码如下:'==========注意==================================
  • 这次讨论一下关于select元素的一个问题,其实很早以前我就碰到过关于select元素的问题,这次做网站又被问到同样的问题,就是:一般div
  •        多表操作 在一个数据库中,可能存在多个表,这些表都是相互关联的。我
  • 关于段落<p></p>相信大家已经都在自己的工作中开始关注并应用了。因为那真的是非常简单的事,只要你愿意你随时都可以
  • 两个并发事务同时访问数据库表相同的行时,可能存在以下三个问题:1、幻想读:事务T1读取一条指定where条件的语句,返回结果集。此时事务T2
  • 其实在很久很久之前就发现search类型的input,该属性值是WebKit私有,不过一直没去查相关的属性,介于XXX原因,我找出其属性,回
  • MySQL使用环境变量TMPDIR的值作为保存临时文件的目录的路径名。如果未设置TMPDIR,MySQL将使用系统的默认值,通常为/tmp、
  • QQ登录Banner增加了剧情的概念之后,已经推出了春节和情人节两期。这之后设想能围绕Banner做的更加丰富,对传统文化的体现也能更为深入
  • javascript模仿alert提示效果,如果你听厌倦了系统自带的那个,可以使用这个alert提示效果,听不错的。相关文章推荐《类似于新浪
  • match()方法用于从字符串中查找指定的值本方法类似于indexOf()和lastindexOf(),不同的是它返回的是指定的值,而不是指
  • 例如:我们在百度中搜索 词典网,则网址后面的参数就是http://www.baidu.com/s?cl=3&wd=%B4%CA%B5
  • 这个弹出层的登录界面挺好看,很清爽所以转了过来给大家分享,要实现这个功能很简单:首先设计一个登录界面,使用css中的display=&quo
  • 1、页签的表达。页签表达很清晰,当前页签突出,且层级包涵关系明确;看下图,一目了然的感觉,不用疑惑我在那部分里。不信?拿当当的对比一下,你感
  • // 执行AJAX请求的通用函数//带一个参数,是包含一系列选项的对象function ajax(options){//如果用户没有提供某个
手机版 网络编程 asp之家 www.aspxhome.com