hibernate自增主键的并发问题
先准备环境,mysql新建test表有一个自增主键叫id,并且有一记录当前时间的日期字段。如下:

测试代码:
hibernate自增主键的实现的两种方案
1.increment方式
Hibernate: select max(id) from test
incId:12
Hibernate: insert into test (name, id) values (?, ?)
这说明该方式是在save方法执行后,事务提交前用max(id)方式获取自增id的,并发测试结果会发生重复主键情况
2.native方式
执行测试代码可看到日志:
Hibernate: insert into test (name) values (?)
测试:
线程1:在提交事务之前(commit前一行)加入较长时间执行的程序.
线程2:代码不变(会比线程1早提交)
可以发现,线程1的id是比线程2的id小的。但是时间字段值线程1比线程2的值大,说明是后提交到数据库的。
由上述例子可以看出:使用native的方式,在事务开启时分配id,多线程时可以避免重复主键问题
3.最后再debug看一下hibernate是怎么取得返回主键值的。
保存对象时使用的代码是org.hibernate.Session.save(obj);
Session的实现类是SessionImpl,如下图堆栈所示,最后进入了GetGeneratedKeysHelper.的getGeneratedKey方法:

再看这个方法的实现:

这里可看出他是使用了java.sql.Statement.getGeneratedKeys方法取得自增主键的。
文/程忠 浏览次数:0次 2015-03-16 09:16:07

测试代码:
Configuration configuration = new Configuration(); configuration.configure("/hibernate.cfg.xml"); SessionFactory sessionFactory = configuration.buildSessionFactory(); Session session = sessionFactory.getCurrentSession(); Transaction tr=session.beginTransaction(); Test t=new Test(); t.setName("23"); Serializable id=session.save(t); System.out.println("incId:"+id); tr.commit();
hibernate自增主键的实现的两种方案
1.increment方式
<id name="id" type="java.lang.Integer"> <column name="id" length="11"> </column> <generator class="increment" /> </id>
Hibernate: select max(id) from test
incId:12
Hibernate: insert into test (name, id) values (?, ?)
这说明该方式是在save方法执行后,事务提交前用max(id)方式获取自增id的,并发测试结果会发生重复主键情况
2.native方式
<id name="id" type="java.lang.Integer"> <column name="id" length="11"> </column> <generator class="native" /> </id>
执行测试代码可看到日志:
Hibernate: insert into test (name) values (?)
测试:
线程1:在提交事务之前(commit前一行)加入较长时间执行的程序.
线程2:代码不变(会比线程1早提交)
可以发现,线程1的id是比线程2的id小的。但是时间字段值线程1比线程2的值大,说明是后提交到数据库的。
由上述例子可以看出:使用native的方式,在事务开启时分配id,多线程时可以避免重复主键问题
3.最后再debug看一下hibernate是怎么取得返回主键值的。
保存对象时使用的代码是org.hibernate.Session.save(obj);
Session的实现类是SessionImpl,如下图堆栈所示,最后进入了GetGeneratedKeysHelper.的getGeneratedKey方法:

再看这个方法的实现:

这里可看出他是使用了java.sql.Statement.getGeneratedKeys方法取得自增主键的。
相关阅读
评论:
↓ 广告开始-头部带绿为生活 ↓
↑ 广告结束-尾部支持多点击 ↑