您应该将@Transactional放在DAO类和/或它们的方法中,还是更好地注释使用DAO对象调用的服务类?或者对两个“层”都加注释有意义吗?
当前回答
服务层中的@事务使用是通过使用控制器层(@Controller)调用的,服务层调用DAO层(@Repository),即数据库相关的操作。
其他回答
最好把它放在服务层!这在我昨天看到的一篇文章中有清楚的解释!这是你可以查看的链接!
或者对两个“层”都加注释有意义吗?-同时标注服务层和dao层不是很有意义吗-如果你想确保dao方法总是从服务层调用(传播),并且在dao中传播是“强制的”。这将为DAO方法从UI层(或控制器)调用提供一些限制。此外——特别是在对DAO层进行单元测试时——对DAO进行注释还将确保对其事务功能进行测试。
最好将@Transactional放在DAO和服务层之间的单独中间层中。 由于回滚非常重要,您可以将所有的DB操作放在中间层,并在服务层中编写业务逻辑。中间层将与DAO层交互。
这将帮助您在许多情况下,如ObjectOptimisticLockingFailureException -此异常只发生在您的事务结束后。所以,你不能在中间层捕获它,但你现在可以在服务层捕获它。如果在服务层中有@Transactional,这是不可能的。虽然你可以在控制器中捕获,但控制器应该尽可能干净。
如果您在完成所有保存、删除和更新选项后在单独的线程中发送邮件或短信,您可以在中间层事务完成后在服务中执行此操作。同样,如果你在服务层提到@Transactional,即使你的事务失败,你的邮件也会被发送。
所以有一个中间的@Transaction层将有助于使你的代码更好,更容易处理。否则, 如果在DAO层使用,可能无法回滚所有操作。 如果在服务层使用,在某些情况下可能必须使用AOP(面向方面编程)。
总的来说,我同意其他人的说法,事务通常在服务级别上启动(当然,这取决于您需要的粒度)。
然而,与此同时,我也开始在我的DAO层(以及其他不允许启动事务但需要现有事务的层)中添加@Transactional(propagation = propagation . mandatory),因为当您忘记在调用者(例如服务)中启动事务时,检测错误要容易得多。如果您的DAO带有强制传播注释,则会得到一个异常,说明在调用方法时没有活动事务。
我还进行了一个集成测试,在该测试中,我检查了所有bean (bean后处理器)的该注释,如果在不属于服务层的bean中存在传播方式不是Mandatory的@Transactional注释,则会失败。这样可以确保我们不会在错误的层上启动事务。
我将@Transactional放在@Service层,并设置rollbackFor任何异常和readOnly以进一步优化事务。
默认情况下@Transactional将只查找RuntimeException(未检查的异常),通过将回滚设置为exception. class(已检查的异常),它将回滚任何异常。
@Transactional(readOnly = false, rollbackFor = Exception.class)
参见已检查异常和未检查异常。
推荐文章
- codestyle;把javadoc放在注释之前还是之后?
- 如何在Spring中定义List bean ?
- 将Set<T>转换为List<T>的最简洁的方法
- 在JavaScript中,什么相当于Java的Thread.sleep() ?
- 使用Java重命名文件
- URL从Java中的类路径加载资源
- .toArray(new MyClass[0]) or .toArray(new MyClass[myList.size()])?
- Hibernate中不同的保存方法之间有什么区别?
- Java 8流和数组操作
- Java Regex捕获组
- Openssl不被视为内部或外部命令
- 如何添加自定义方法到Spring Data JPA
- 如何在Ubuntu中设置Java环境路径
- 无法执行dex:在Eclipse中超过GC开销限制
- 有人能解释一下JPA和Hibernate中的mappedBy吗?