hibernate中的事务提交
Posted
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了hibernate中的事务提交相关的知识,希望对你有一定的参考价值。
请问各位为什么我的事务commit的时候就报错 identifier of an instance of....,我查了网上的一些信息,说是更新的时候出了不同的id。但我这是查询语句,并没有保存更新啊。
userName不是主键。
以下是部分代码:
tx = session.beginTransaction();
Query query = session.createQuery("from Player p where p.userName=?");
query.setString(0, name);
playerlist = query.list();
if (playerlist.size()>0)
for (int i = 0; i < playerlist.size(); i++)
player = (Player)playerlist.get(i);
tx.commit();
谢谢你的回答,player 确实有值,是从数据库读出来的。我试过把player = (Player)playerlist.get(i)去掉,只留下i如下代码:tx = session.beginTransaction();
Query query = session.createQuery("from Player p where p.userName=?");
query.setString(0, name);
playerlist = query.list();
tx.commit();
但同样报这个错误,不知为什么。好像我只要掉用query的方法就出错。
如果player在上面的代码中是不为null,并且该对象的数据是保存到数据库过的,也就是进行了持久化的。由于hibernate使用缓存,player = (Player)playerlist.get(i);也就是重新给之前持久化过的实例player进行了赋值,player进行了更新,更新操作会在事务中提交。而此处多次循环赋值,并且都是已经保存过的数据,所以id肯定是重复的,也就报错了。
针对调用Query方法出错,是不是可能导包的时候弄错了,请确认导入的Query类是否为org.hibernate.Query;追问
导入的确实是org.hibernate.Query类。不过,现在我把它改成不用事务提交的了,直接查询,不用事务了。
追答如果导包正确了,还出错比较奇怪。
查询,不用事务控制,不影响使用,因为不涉及数据库数据修改,不需要在错误时回滚数据。
Hibernate 如何在提交事务之前对 Optimistic Locking 进行行版本检查
【中文标题】Hibernate 如何在提交事务之前对 Optimistic Locking 进行行版本检查【英文标题】:How does Hibernate do row version check for Optimistic Locking before committing the transaction 【发布时间】:2019-03-30 00:11:37 【问题描述】:当在提交当前事务之前休眠检查行的版本,它应该发出一个 sql select
语句来获取它。
假设在发出select
语句后休眠发现行版本没有改变,因此它应该继续提交事务。
我想知道 hibernate 如何确保在选择行和提交当前事务之间的时间段内没有任何其他事务会更新该行以更改其版本号? hibernate 唯一可能做的事情似乎是使用Select ... For Update
进行悲观锁定的行版本选择或具有这样一个隔离级别的事务,它将锁定正在读取的行。
如果我的想法是真的:
那么休眠乐观锁确实使用悲观锁来进行操作,尽管该悲观锁的持有时间很短,因为此后事务将立即提交。
否则,我们在行版本检查和提交之间的时间间隔很短,可能会出现竞争条件。
请分享你的想法。
【问题讨论】:
【参考方案1】:对于默认的乐观锁机制,@Version
注解给出的机制,没有这种风险。
乐观锁定不需要任何额外的 SELECT 来获取和检查实体修改后的版本。因此,涉及两个步骤:
从数据库中获取实体及其版本:
SELECT * FROM PRODUCT WHERE ID = 1;
UPDATE 或 DELETE 将使用获取实体的同一 SELECT 获取的版本:
UPDATE PRODUCT SET (LIKES, QUANTITY, VERSION) = (5, 10, 3)
WHERE ID = 1 AND VERSION = 2;
因此,Hibernate 不会检查实体版本。数据库使用 WHERE 子句对其进行检查。
Hibernate 只检查PreparedStatement.executeUpdate
方法调用的updateCount
结果。如果计数不是updateCount
,则表示该行已被删除或版本已更改,这意味着我们使用的是陈旧数据,因此将抛出OptimisticLockException
。
因此,默认的基于@Version
的乐观锁定不会发生冲突,因为一条记录一次只能被一个事务修改,并且一旦该行被修改锁定,锁定将一直保留到事务提交或回滚。
只有显式的LockModeType.OPTIMISTIC
才能导致竞争条件。不过,您可以轻松fix that using a pessimistic shared or explicit lock。
【讨论】:
以上是关于hibernate中的事务提交的主要内容,如果未能解决你的问题,请参考以下文章
无法提交 Hibernate 事务;嵌套异常是 org.hibernate.Transaction 异常:JDBC 提交失败