如何在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层加事务,在spring.xml的aop:config添加对Controller的声明式事务拦截,结果未生效。在Controller的class加上@Transactional也未生效。最后采取的编程式事务实现的。
我们在Spring.xml配置sessionFactory和transactionManager,如果已经配置声明式事务,这步可以忽略。

<bean id="sessionFactory"
        class="org.springframework.orm.hibernate3.annotation.AnnotationSessionFactoryBean">
        <property name="dataSource" ref="c3p0DataSource" />
        <property name="hibernateProperties">
            <props>
                <prop key="hibernate.dialect">#{ nplat['db.dialect'] }</prop>
                <prop key="hibernate.hbm2ddl.auto">none</prop>
                <prop key="hibernate.connection.release_mode">after_transaction</prop>
                <prop key="hibernate.show_sql">false</prop>
                <prop key="hibernate.format_sql">false</prop>
                <prop key="hibernate.max_fetch_depth">3</prop><!-- 抓取的级联深度 -->
                <prop key="hibernate.jdbc.fetch_size">50</prop><!-- 批量抓取的数量.mysql不支持 -->
                <prop key="hibernate.jdbc.batch_size">30</prop><!-- 批量写入的数量 -->
                <prop key="javax.persistence.validation.mode">none</prop><!-- HiberV3.5以上需配置该项 -->
                <!-- <prop key="hibernate.cache.use_second_level_cache">true</prop> <prop 
                    key="hibernate.cache.use_query_cache">false</prop> <prop key="hibernate.cache.provider_class">org.hibernate.cache.EhCacheProvider</prop> 
                    强制Hibernate以更人性化的格式将数据存入二级缓存 <prop key="hibernate.cache.use_structured_entries">true</prop> -->
            </props>
        </property>
        <property name="packagesToScan">
            <list>
                <value>com.gina.gc</value>
            </list>
        </property>
    </bean>

    <bean id="transactionManager"
        class="org.springframework.orm.hibernate3.HibernateTransactionManager">
        <property name="sessionFactory">
            <ref bean="sessionFactory" />
        </property>
    </bean>

然后在每个Controller注入transactionManager:

@Resource
private PlatformTransactionManager transactionManager;

下面讲解如何在Controller的save方法加上编程式事务:

@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();
}

这样我们便实现了在Controller层加上事务管理。
虽说大家建议把事务加在Service,但不同情况不同处理方案,真正到项目中还得综合考虑,灵活运用。

  • 5
    点赞
  • 13
    收藏
    觉得还不错? 一键收藏
  • 17
    评论
如果在Controller不加事务注解,则`service1.method1()`和`service2.method2()`方法默认会在各自的事务中执行,这样就无法保证事务的一致性,即使其中一个方法执行失败,也不会回滚整个事务。 如果希望在Controller不加事务注解的情况下,仍然能够保证多个Service方法在同一事务中执行,可以使用编程式事务管理。具体实现方式是在Controller方法中获取`TransactionTemplate`对象,然后通过该对象手动开启事务、提交事务或回滚事务。示例代码如下: ```java @Service public class MyService1 { public void method1() { //... } } @Service public class MyService2 { public void method2() { //... } } @Controller public class MyController { @Autowired private MyService1 service1; @Autowired private MyService2 service2; @Autowired private PlatformTransactionManager transactionManager; public void controllerMethod() { TransactionTemplate transactionTemplate = new TransactionTemplate(transactionManager); transactionTemplate.execute(status -> { try { service1.method1(); service2.method2(); return true; } catch (Exception e) { status.setRollbackOnly(); return false; } }); } } ``` 在上述示例中,`MyController`的`controllerMethod`方法中首先获取了`TransactionTemplate`对象,然后在该对象的`execute`方法中执行`service1.method1()`和`service2.method2()`方法,并手动开启、提交或回滚事务。如果其中一个方法执行失败,则会回滚整个事务,保证事务的一致性。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 17
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值