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


当前回答

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

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

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

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

其他回答

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

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

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

理想情况下,服务层(管理器)表示业务逻辑,因此应该用@Transactional进行注释。服务层可以调用不同的DAO来执行DB操作。让我们假设在一个服务方法中有N个DAO操作。如果您的第一个DAO操作失败,其他DAO操作可能仍然通过,您将以不一致的DB状态结束。注释服务层可以避免这种情况。

我更喜欢在方法级的服务层上使用@Transactional。

我认为事务属于服务层。它了解工作单元和用例。如果将几个dao注入到需要在单个事务中协同工作的服务中,这是正确的答案。

通常情况下是在服务层级别上注释,但这实际上取决于您的需求。

在服务层上注释将比在DAO层上注释产生更长的事务。这取决于事务隔离级别,可以产生问题,因为并发事务不会看到彼此的更改,例如。可重复读。

在dao上注释将使事务尽可能简短,缺点是您的服务层公开的功能不会在单个(可回滚的)事务中完成。

如果传播模式被设置为默认,那么对两个层都进行注释就没有意义了。