【问题标题】:Why does Hibernate throw org.hibernate.exception.LockAcquisitionException?为什么 Hibernate 会抛出 org.hibernate.exception.LockAcquisitionException?
【发布时间】:2014-09-25 16:53:09
【问题描述】:

我有这个方法:

mymethod(long id){  
    Person p = DAO.findPerson(id);

    Car car = new Car();
    car.setPerson(p);
    p.getCars().add(car);

    DAO.saveOrUpdate(car);
    DAO.saveOrUpdate(p);
    DAO.delete(p.getCars().get(0));//A person have many cars
}  

映射:

Person.hbm.xml

<!-- one-to-many : [1,1]-> [0,n] -->
<set name="car" table="cars" lazy="true" inverse="true">
    <key column="id_doc" />
    <one-to-many class="Car" />
</set>

<many-to-one name="officialCar"
class="Car" 
column="officialcar_id" lazy="false"/>  

汽车.hbm.xml

<many-to-one name="person" class="Person"
            column="id_person" not-null="true" lazy="false"/>   

此方法适用于单个线程,但在多个线程上,给我一个错误:

02/08/2014 - 5:19:11 p.m. - [pool-1-thread-35] - WARN - org.hibernate.util.JDBCExceptionReporter - SQL Error: 60, SQLState: 61000 
02/08/2014 - 5:19:11 p.m. - [pool-1-thread-35] - ERROR - org.hibernate.util.JDBCExceptionReporter - ORA-00060: deadlock detection while waiting for a resource 
 
02/08/2014 - 5:19:11 p.m. - [pool-1-thread-35] - WARN - org.hibernate.util.JDBCExceptionReporter - SQL Error: 60, SQLState: 61000 
02/08/2014 - 5:19:11 p.m. - [pool-1-thread-35] - ERROR - org.hibernate.util.JDBCExceptionReporter - ORA-00060: deadlock detection while waiting for a resource 
 
02/08/2014 - 5:19:11 p.m. - [pool-1-thread-35] - ERROR - org.hibernate.event.def.AbstractFlushingEventListener - Could not synchronize database state with session 
org.hibernate.exception.LockAcquisitionException: Could not execute JDBC batch update

AOP 事务:

<tx:advice id="txAdviceNomService" transaction-manager="txManager">
    <tx:attributes>
        <tx:method name="*" propagation="REQUIRED" rollback-for="java.lang.Exception" />
        <tx:method name="getAll*" read-only="true" propagation="SUPPORTS" />
        <tx:method name="find*" read-only="true" propagation="SUPPORTS" />
    </tx:attributes>
</tx:advice>

注意:当我在更新后添加 Thread.sleep(5000) 时,没关系。但是这个解决方案并不干净。

【问题讨论】:

标签: java spring oracle hibernate transactions


【解决方案1】:

根据您的映射,操作顺序应如下所示:

Person p = DAO.findPerson(id);

Car car = new Car();
car.setPerson(p);

DAO.saveOrUpdate(car);

p.getCars().add(car);

Car firstCar = p.getCars().get(0);
firstCar.setPerson(null);
p.getCars().remove(firstCar);
if (p.officialCar.equals(firstCar)) {
   p.officialCar = null;
   p.officialCar.person = null;
}

DAO.delete(firstCar);

更新删除意味着获取独占锁,即使在READ_COMMITTED隔离级别。

如果另一个事务想要用当前正在运行的事务(已经锁定该行)更新同一行,您将不会遇到死锁,但会出现锁获取超时异常。

由于你遇到了死锁,这意味着你在多个表上获取了锁,并且锁获取的顺序不正确。

因此,请确保服务层方法设置事务边界,而不是 DAO 方法。我看到您声明了使用 SUPPORTED 的 getfind 方法,这意味着它们仅在当前启动时才会使用事务。我认为您也应该使用 REQUIRED,但只需将它们标记为 read-only = true

因此,请确保事务方面将事务边界应用于“mymethod”而不是 DAO 。

【讨论】:

  • 事务申请到mymethod。我更改了问题的代码。
  • 您不需要为 Person 调用 saveOrUpdate,为新车调用它。 person.cars 是单向的吗?如果没有设置 cat.person ,保存/删除时。
  • 谢谢弗拉德。我更改了代码。但我也有同样的问题。
  • 你能发布汽车和人的映射吗?
  • 也更新了我的回复。
【解决方案2】:

我有汽车 -> (1 -n) 个地方。 而且我在表位置(id_car)中有一个外键。这个外键没有索引。 当我为这个外键添加索引时,我的问题就解决了。

参考This Answer

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2011-04-06
    • 1970-01-01
    • 2010-11-06
    • 1970-01-01
    • 2011-05-26
    • 2014-08-14
    • 2020-12-27
    • 2021-12-20
    相关资源
    最近更新 更多