您应该将@Transactional放在DAO类和/或它们的方法中,还是更好地注释使用DAO对象调用的服务类?或者对两个“层”都加注释有意义吗?
当前回答
总的来说,我同意其他人的说法,事务通常在服务级别上启动(当然,这取决于您需要的粒度)。
然而,与此同时,我也开始在我的DAO层(以及其他不允许启动事务但需要现有事务的层)中添加@Transactional(propagation = propagation . mandatory),因为当您忘记在调用者(例如服务)中启动事务时,检测错误要容易得多。如果您的DAO带有强制传播注释,则会得到一个异常,说明在调用方法时没有活动事务。
我还进行了一个集成测试,在该测试中,我检查了所有bean (bean后处理器)的该注释,如果在不属于服务层的bean中存在传播方式不是Mandatory的@Transactional注释,则会失败。这样可以确保我们不会在错误的层上启动事务。
其他回答
或者对两个“层”都加注释有意义吗?-同时标注服务层和dao层不是很有意义吗-如果你想确保dao方法总是从服务层调用(传播),并且在dao中传播是“强制的”。这将为DAO方法从UI层(或控制器)调用提供一些限制。此外——特别是在对DAO层进行单元测试时——对DAO进行注释还将确保对其事务功能进行测试。
通常,应该将事务放在服务层。
但是正如前面所述,操作的原子性告诉我们哪里需要注释。因此,如果你使用像Hibernate这样的框架,其中一个“save/update/delete/…”一个对象上的“modify”操作有可能修改几个表中的几行(因为通过对象图的级联),当然在这个特定的DAO方法上也应该有事务管理。
首先,让我们定义一下在什么地方使用事务?
我认为正确的答案是——当我们需要确保动作序列将作为一个原子操作一起完成时,或者即使其中一个动作失败,也不会进行任何更改。
将业务逻辑放入服务中是众所周知的实践。因此,服务方法可能包含必须作为单个逻辑工作单元执行的不同操作。如果是,那么这种方法必须被标记为事务性的。当然,并不是每个方法都需要这样的限制,所以您不需要将整个服务标记为事务性的。
更重要的是,不要忘记考虑@Transactional可能会降低方法性能。 为了了解全局,您必须了解事务隔离级别。了解这一点可以帮助您避免在不必要的地方使用@Transactional。
总的来说,我同意其他人的说法,事务通常在服务级别上启动(当然,这取决于您需要的粒度)。
然而,与此同时,我也开始在我的DAO层(以及其他不允许启动事务但需要现有事务的层)中添加@Transactional(propagation = propagation . mandatory),因为当您忘记在调用者(例如服务)中启动事务时,检测错误要容易得多。如果您的DAO带有强制传播注释,则会得到一个异常,说明在调用方法时没有活动事务。
我还进行了一个集成测试,在该测试中,我检查了所有bean (bean后处理器)的该注释,如果在不属于服务层的bean中存在传播方式不是Mandatory的@Transactional注释,则会失败。这样可以确保我们不会在错误的层上启动事务。
我认为事务属于服务层。它了解工作单元和用例。如果将几个dao注入到需要在单个事务中协同工作的服务中,这是正确的答案。
推荐文章
- 在流中使用Java 8 foreach循环移动到下一项
- 访问限制:'Application'类型不是API(必需库rt.jar的限制)
- 用Java计算两个日期之间的天数
- 如何配置slf4j-simple
- 在Jar文件中运行类
- 带参数的可运行?
- 我如何得到一个字符串的前n个字符而不检查大小或出界?
- 我可以在Java中设置enum起始值吗?
- Java中的回调函数
- c#和Java中的泛型有什么不同?和模板在c++ ?
- 在Java中,流相对于循环的优势是什么?
- Jersey在未找到InjectionManagerFactory时停止工作
- 在Java流是peek真的只是调试?
- Recyclerview不调用onCreateViewHolder
- 将JSON字符串转换为HashMap