您应该将@Transactional放在DAO类和/或它们的方法中,还是更好地注释使用DAO对象调用的服务类?或者对两个“层”都加注释有意义吗?
当前回答
服务层中的@事务使用是通过使用控制器层(@Controller)调用的,服务层调用DAO层(@Repository),即数据库相关的操作。
其他回答
服务层是添加@Transactional注释的最佳位置,因为这里呈现的大多数业务逻辑都包含细节级用例行为。
假设我们将它添加到DAO,从服务调用2个DAO类,一个失败,另一个成功,在这种情况下,如果@Transactional不在服务上,一个DB将提交,另一个DB将回滚。
因此,我的建议是明智地使用这个注释,只在服务层使用。
Github项目- java-algos
传统Spring体系结构的正确答案是将事务语义放在服务类上,原因其他人已经描述过了。
An emerging trend in Spring is toward domain-driven design (DDD). Spring Roo exemplifies the trend nicely. The idea is to make the domain object POJOs a lot richer than they are on typical Spring architectures (usually they are anemic), and in particular to put transaction and persistence semantics on the domain objects themselves. In cases where all that's needed is simple CRUD operations, the web controllers operate directly on the domain object POJOs (they're functioning as entities in this context), and there's no service tier. In cases where there's some kind of coordination needed between domain objects, you can have a service bean handle that, with @Transaction as per tradition. You can set the transaction propagation on the domain objects to something like REQUIRED so that the domain objects use any existing transactions, such as transactions that were started at the service bean.
从技术上讲,这种技术使用了AspectJ和<context:spring-configured />。Roo使用AspectJ类型间定义将实体语义(事务和持久性)与领域对象(基本上是字段和业务方法)分离开来。
理想情况下,服务层(管理器)表示业务逻辑,因此应该用@Transactional进行注释。服务层可以调用不同的DAO来执行DB操作。让我们假设在一个服务方法中有N个DAO操作。如果您的第一个DAO操作失败,其他DAO操作可能仍然通过,您将以不一致的DB状态结束。注释服务层可以避免这种情况。
用于数据库级别的事务
大多数情况下,我在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放在DAO和服务层之间的单独中间层中。 由于回滚非常重要,您可以将所有的DB操作放在中间层,并在服务层中编写业务逻辑。中间层将与DAO层交互。
这将帮助您在许多情况下,如ObjectOptimisticLockingFailureException -此异常只发生在您的事务结束后。所以,你不能在中间层捕获它,但你现在可以在服务层捕获它。如果在服务层中有@Transactional,这是不可能的。虽然你可以在控制器中捕获,但控制器应该尽可能干净。
如果您在完成所有保存、删除和更新选项后在单独的线程中发送邮件或短信,您可以在中间层事务完成后在服务中执行此操作。同样,如果你在服务层提到@Transactional,即使你的事务失败,你的邮件也会被发送。
所以有一个中间的@Transaction层将有助于使你的代码更好,更容易处理。否则, 如果在DAO层使用,可能无法回滚所有操作。 如果在服务层使用,在某些情况下可能必须使用AOP(面向方面编程)。
推荐文章
- 在流中使用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