您应该将@Transactional放在DAO类和/或它们的方法中,还是更好地注释使用DAO对象调用的服务类?或者对两个“层”都加注释有意义吗?


当前回答

总的来说,我同意其他人的说法,事务通常在服务级别上启动(当然,这取决于您需要的粒度)。

然而,与此同时,我也开始在我的DAO层(以及其他不允许启动事务但需要现有事务的层)中添加@Transactional(propagation = propagation . mandatory),因为当您忘记在调用者(例如服务)中启动事务时,检测错误要容易得多。如果您的DAO带有强制传播注释,则会得到一个异常,说明在调用方法时没有活动事务。

我还进行了一个集成测试,在该测试中,我检查了所有bean (bean后处理器)的该注释,如果在不属于服务层的bean中存在传播方式不是Mandatory的@Transactional注释,则会失败。这样可以确保我们不会在错误的层上启动事务。

其他回答

最好把它放在服务层!这在我昨天看到的一篇文章中有清楚的解释!这是你可以查看的链接!

用于数据库级别的事务

大多数情况下,我在DAO的方法级别上使用@Transactional,所以配置可以专门用于一个方法/使用默认值(必需的)

DAO获取数据的方法(select ..)-不需要 @事务性这可能会导致一些开销,因为 事务拦截器/和需要执行的AOP代理 好。 DAO的插入/更新方法将获得@Transactional

非常好的博客

应用级别: 我正在使用事务性业务逻辑,我希望能够在发生意外错误的情况下回滚

@Transactional(rollbackFor={MyApplicationException.class})
public void myMethod(){

    try {    
        //service logic here     
    } catch(Throwable e) {

        log.error(e)
        throw new MyApplicationException(..);
    }
}

首先,让我们定义一下在什么地方使用事务?

我认为正确的答案是——当我们需要确保动作序列将作为一个原子操作一起完成时,或者即使其中一个动作失败,也不会进行任何更改。

将业务逻辑放入服务中是众所周知的实践。因此,服务方法可能包含必须作为单个逻辑工作单元执行的不同操作。如果是,那么这种方法必须被标记为事务性的。当然,并不是每个方法都需要这样的限制,所以您不需要将整个服务标记为事务性的。

更重要的是,不要忘记考虑@Transactional可能会降低方法性能。 为了了解全局,您必须了解事务隔离级别。了解这一点可以帮助您避免在不必要的地方使用@Transactional。

我将@Transactional放在@Service层,并设置rollbackFor任何异常和readOnly以进一步优化事务。

默认情况下@Transactional将只查找RuntimeException(未检查的异常),通过将回滚设置为exception. class(已检查的异常),它将回滚任何异常。

@Transactional(readOnly = false, rollbackFor = Exception.class)

参见已检查异常和未检查异常。

或者对两个“层”都加注释有意义吗?-同时标注服务层和dao层不是很有意义吗-如果你想确保dao方法总是从服务层调用(传播),并且在dao中传播是“强制的”。这将为DAO方法从UI层(或控制器)调用提供一些限制。此外——特别是在对DAO层进行单元测试时——对DAO进行注释还将确保对其事务功能进行测试。