如何在Controller层实现事务管理?
有时候我i们需要让一个controller中的操作数据库的方法一下走完,如果发生错误就要回滚之前的插入的所有的数据,这个时候就需要controller事务了。
在spring aop 事务管理中发现,我们是在service层实现的事务管理。
现在有如下场景,大家讨论下看如何实现?
ControllerA、ControllerB、ControllerC….共同依赖ServiceA、ServiceB,上述Controller的save操作需要把数据同步ServiceA和ServiceB。
由于每个Controller保存ServiceB的extraData字段是通过Json组装的,所以每个Controller具有独特性。如果在Service层实现事务管理,ServiceA将会变的异常庞大,需要判断是哪个Controller过来的数据,然后组装ServiceB的extraData字段。
另一种思路,我们是否可以把每个Controller组装ServiceB的extraData字段过程放在各自的Controller,然后在Controller实现事务管理呢?
经过测试,在Controller层加事务,在applicationContext-tx.xml的aop:config添加对Controller的声明式事务拦截,结果未生效。在Controller的class加上@Transactional也未生效。最后采取的编程式事务实现的。
我们在applicationContext-tx.xml配置sessionFactory和transactionManager,如果已经配置声明式事务,这步可以忽略。
第一种方法:
虽说建议把事务加在Service,但不同情况不同处理方案,真正到项目中还得综合考虑,灵活运用。
applicationContext-tx.xml
<beans xmlns="http://www.springframework.org/schema/beans"
xmlns:context="http://www.springframework.org/schema/context" xmlns:p="http://www.springframework.org/schema/p"
xmlns:aop="http://www.springframework.org/schema/aop" xmlns:tx="http://www.springframework.org/schema/tx"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans-4.2.xsd
http://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context-4.2.xsd
http://www.springframework.org/schema/aop http://www.springframework.org/schema/aop/spring-aop-4.2.xsd http://www.springframework.org/schema/tx http://www.springframework.org/schema/tx/spring-tx-4.2.xsd
http://www.springframework.org/schema/util http://www.springframework.org/schema/util/spring-util-4.2.xsd">
<!-- 事务管理器 -->
<bean id="transactionManager"
class="org.springframework.jdbc.datasource.DataSourceTransactionManager">
<!-- 数据源 -->
<property name="dataSource" ref="dataSource" />
</bean>
<!-- 通知 -->
<tx:advice id="txAdvice" transaction-manager="transactionManager">
<tx:attributes>
<!-- 传播行为 -->
<tx:method name="save*" propagation="REQUIRED" />
<tx:method name="insert*" propagation="REQUIRED" />
<tx:method name="add*" propagation="REQUIRED" />
<tx:method name="create*" propagation="REQUIRED" />
<tx:method name="delete*" propagation="REQUIRED" />
<tx:method name="update*" propagation="REQUIRED" />
<tx:method name="find*" propagation="SUPPORTS" read-only="true" />
<tx:method name="select*" propagation="SUPPORTS" read-only="true" />
<tx:method name="get*" propagation="SUPPORTS" read-only="true" />
</tx:attributes>
</tx:advice>
<!-- 切面 -->
<aop:config>
<aop:advisor advice-ref="txAdvice"
pointcut="execution(* com.dhyj.service.*.*(..))" />
</aop:config>
</beans>
@Resourceprivate PlatformTransactionManager transactionManager;
@RequestMapping("/save")
@ResponseBody
public String save(@Validated BaseSetting info) {
DefaultTransactionDefinition defaultTransactionDefinition = new DefaultTransactionDefinition();
defaultTransactionDefinition.setPropagationBehavior(TransactionDefinition.PROPAGATION_REQUIRED);
TransactionStatus status = transactionManager.getTransaction(defaultTransactionDefinition);
try {
serviceA.save(A);
serviceB.save(B);
...
transactionManager.commit(status);
} catch (Exception e) {
transactionManager.rollback(status);
e.printStackTrace();
log.error("sava *** error" + e.toString());
return ERROR(e.toString());
}
return OK();
}
第二种方法:
待续。。。