我有这样的事情:
@Service
@Transactional
public class ServiceA {
@Autowired
SomeDAO1 dao1;
@Autowired
ServiceB serviceB;
public void methodServiceA() {
serviceB.someMethodThatRunsInsertIntoDB();
dao1.anotherMethodThatRunsInsertIntoDB();
}
}
@Service
@Transactional
public class ServiceB {
@Autowired
Dao2 dao2;
public void someMethodThatRunsInsertIntoDB() {
dao2.insertXXX();
}
}
我的问题是:如果serviceB.someMethodThatRunsInsertIntoDB()
执行成功但dao1.anotherMethodThatRunsInsertIntoDB()
抛出异常,则serviceB
所做的更改不会回滚。如果dao1.anotherMethodThatRunsInsertIntoDB()
发生异常,我需要回滚这些更改。我怎么能这样做?
// EDITED
spring-servlet.xml中的事务配置
<bean id="transactionManager" class="org.springframework.orm.jpa.JpaTransactionManager">
<property name="entityManagerFactory" ref="entityManagerFactory" />
<property name="jpaDialect">
<bean class="org.springframework.orm.jpa.vendor.HibernateJpaDialect" />
</property>
</bean>
如果一个dao使用EntityManager而另一个dao使用JdbcTemplate与DB交互是否相关?
// UPDATE - EntityManager配置
<bean id="entityManagerFactory" class="org.springframework.orm.jpa.LocalContainerEntityManagerFactoryBean">
<property name="dataSource" ref="dataSource" />
<property name="jpaVendorAdapter">
<bean class="org.springframework.orm.jpa.vendor.HibernateJpaVendorAdapter">
<property name="showSql" value="true" />
<property name="generateDdl" value="true" />
</bean>
</property>
答案 0 :(得分:2)
您需要传递rollbackFor
参数以及已检查例外的类型。看起来Spring默认只在未经检查的异常上回滚。更多详情:Spring transaction: rollback on Exception or Throwable
答案 1 :(得分:1)
您需要在spring配置文件中使用<tx:annotation-driven/>
来启用注释驱动的事务管理。
答案 2 :(得分:0)
这是因为您的dao1.anotherMethodThatRunsInsertIntoDB()调用不支持当前事务(ServiceA事务)。
您需要在ServiceB类中使用以下传播级别。
@Service
@Transactional(propagation = Propagation.REQUIRED)
public class ServiceB {
必需: Spring REQUIRED行为意味着如果当前bean方法执行上下文中已经打开的事务,将使用相同的事务。如果不存在,则创建一个新的。简而言之,这意味着如果内部(第二个事务)方法导致事务回滚,则外部(第一个事务)方法将无法提交并且还将回滚事务。
传播方式:通常,在事务范围内执行的所有代码都将在该事务中运行。但是,您可以选择在事务上下文已存在时执行事务方法时指定行为。例如,代码可以继续在现有事务中运行(常见情况);或者可以暂停现有交易并创建新交易。 Spring提供了EJB CMT中熟悉的所有事务传播选项。要阅读Spring中事务传播的语义,请参阅Transaction Propagation
编辑 注意:默认情况下,将事务设置为回滚状态的唯一例外是未经检查的异常(如RuntimeException)。如果您希望已检查的异常也将事务设置为回滚,则必须将它们配置为执行此操作, 例如。
@Service
@Transactional(propagation = Propagation.REQUIRED, rollbackFor = YourCheckedException.class))
public class ServiceA {
注意:强> 正如我所注意到的,声明式事务管理是基于AOP的。这意味着Spring将事务bean包装到事务代理中,该代理负责启动和提交事务。这意味着必须由代理拦截方法调用才能成为事务性的。您需要在Spring配置文件中确保以下配置。
<tx:annotation-driven transaction-manager="transactionManager" />
答案 3 :(得分:0)
我的第一个建议是在方法级别使用@Transactional
注释,如果在类级别真的不需要它。
其次,尝试使用javax.transaction.Transactional
注释而不是org.springframework.transaction.annotation.Transactional
,Spring会自动处理传播。
您还需要在使用@Transactional
之前启用事务管理,使用Spring Boot我们可以通过@EnableTransactionManagement
标记Application类来完成此操作。
但是,如果您愿意,您也可以通过XML配置(<tx:annotation-driven />
)完成此操作。请阅读http://docs.spring.io/spring-data/jpa/docs/1.11.0.M1/reference/html/#transactions了解详情