关于服务和@Transactional
Posted
技术标签:
【中文标题】关于服务和@Transactional【英文标题】:On services and @Transactional 【发布时间】:2012-02-19 09:47:45 【问题描述】:如果我有一个服务类连续调用三个其他服务类,并且这些子服务中的每一个都必须在某个时候处理一个 DAO 对象,我该如何让包装服务将它们全部包装到单笔交易?它会像使用@Transactional 注释包装器一样简单吗?如果 DAO 已经标记为 @Transactional 怎么办?
【问题讨论】:
顺便说一句——我不认为你的 DAO 是事务性的。在服务级别,您需要操作是原子的。假设您的服务更新了 Person 及其地址,并且更新地址失败。你想回滚整个事情,对吧?所以@Transactional
注释应该只在服务层的入口点。 (尽管正如响应者所说,您可以嵌套 @Transactional
方法并让它们重用外部事务。)
【参考方案1】:
Spring框架中默认的事务传播是REQUIRED
,这意味着如果事务不存在或者代码加入现有的,则创建事务:
支持当前事务,如果不存在则创建一个新事务。类似于同名的 EJB 事务属性。
这是事务注解的默认设置。
这意味着,如果您将对三个事务方法的调用包装在一个事务方法中,它们都将在一个事务中运行。就这样。
另见:
What is the right way to use spring MVC with Hibernate in DAO, sevice layer architecture【讨论】:
【参考方案2】:如果您将外部服务注释为 @Transactional 并且您的 DAO 也是 @Transactional 并由该服务调用,则默认情况下它们将按照您的希望加入外部事务。
【讨论】:
【参考方案3】:这实际上是一个关于嵌套事务的问题 (http://en.wikipedia.org/wiki/Nested_transaction)。使用 spring,(假设您使用的是版本 3 和注释),REQUIRED 是事务模式的默认值。如果你为你的服务方法设置这个模型,你的“包装器”服务包装的所有方法都将使用宿主事务,这意味着它们将在同一个事务中运行。
【讨论】:
以上是关于关于服务和@Transactional的主要内容,如果未能解决你的问题,请参考以下文章