如果不显式提交事务,Hibernate如何用多个session.update()控制事务?

问题描述 投票:0回答:1

我继承了一个使用Spring MVC和Hibernate的系统,该系统存储在DB2数据库中。最近它开始出现DB2报告的死锁问题,所以我一直在努力调试它。我不是Spring或Hibernate专家,但我对两者都有所了解。

代码的结构是这样的。

controller -> service -> one or more DAO classes that performs the updates

在问题发生的情况下,控制器调用一个服务方法,注解为: @Transactional@Override. 该服务转到一个注解为 @Repository 并调用多个以 @Transactional@Override. 这就是代码的结构。

一个控制器调用一个服务方法。服务方法调用多个DAO方法。大部分的DAO方法都被标记为 @Transactional@Override. 有几项是在 @Transactional. 此外,在每个DAO方法中 Session 得自 SessionFactory.getCurrentSession().

第一个问题:用这种方法,事务从哪里开始,最终的提交在哪里?回滚呢?这些都没有明确的编码。

当其中一个方法更新了一条记录,然后后续的方法又删除了同一条记录时,就会出现死锁。如果你想知道为什么有人要这么做,更新会添加想要删除记录中信息的人的用户id,这样就可以通过存储过程将其保存到另一个表中。然后第二个方法调用就会删除记录。

原先的编码员尝试着将REQUIRES_NEW添加到 @Transactional 以为新的事务会确保更新的发生。但是死锁还是不定时的发生。

我试着将更新改为本地SQL调用,但Hibernate不会让我启动另一个事务,因为一个事务已经打开了。

有人在这里有什么指导吗?

java spring hibernate db2 database-deadlocks
1个回答
1
投票

事务开始时,一个方法(哪个类或方法本身首先注解为:"Spring MVC "或 "Hibernate")在DB2的数据库中存储。@Transactional 在调用链中)从外部调用(它必须从类的外部调用,因为该注解 "创建 "了一个代理)。链中任何其他注解的类方法的默认传播级别都将加入到该事务中。当调用一个标有事务性的方法时,该方法会被标记为 REQUIRES_NEW父事务将被暂停(如果存在的话),并开始新的事务。请注意,如果你从同一个类中的其他方法中调用注解的方法,那么它将不会通过代理,所以这和你删除注解一样。提交发生在启动事务的方法返回之后。和回滚一样,在抛出异常后就会发生。死锁可能来自不同的地方,即使你有代码也很难发现。例如,它可能来自于更新和存储过程试图锁定一些行和循环等待等。

我有一个天真的图像,在后台发生了什么,有两个类ui和服务。服务被注释为 @Transactional.Spring创建代理,所有来自外部的调用都要经过它。在真正的方法被调用之前,它将启动事务,之后它将提交。

enter image description here

© www.soinside.com 2019 - 2024. All rights reserved.