首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >从使用datasoure事务的其他服务调用时,在其自己的数据源事务中运行方法

从使用datasoure事务的其他服务调用时,在其自己的数据源事务中运行方法
EN

Stack Overflow用户
提问于 2016-06-23 18:09:34
回答 1查看 29关注 0票数 0

我有一个场景,其中使用了两个不同的数据源。

DataSource1服务类(支持事务)调用DataSource2服务类方法(支持事务,但带有datasource2)

代码如下所示。我的需求是如何在一个单独的事务中运行persistOneByOne(),当我们调用这个hierarchy.If异常时,不要持久化那个记录,但是因为它在for循环中继续处理其他记录。我如何实现此行为。

// Service class 2使用数据源-1,它是由aop启用的事务

代码语言:javascript
复制
public class DataSource1ServiceClass1{
    DataSource2OtherServiceClass service2;

     public void processData(){
           service2.prepareAndPeristData();
      }
    }

// Service class 2使用另一个名为datasource-2的数据源,它也是由aop启用的事务

代码语言:javascript
复制
public class DataSource2OtherServiceClass{

     public void prepareAndPeristData(){
         try{
            for(int i=0;i<10;i++)
              {
            // pre processing before persisting a single record
            persistOneByOne();
              }
            }catch (Exception e){
               log.error("Error occurred.. so didn't persist record as expected"};
            }


     public void persistOneByOne()
       {
          dao.persist();
       } 
}

配置xml文件:

代码语言:javascript
复制
<bean id="txManager"
        class="org.springframework.jdbc.datasource.DataSourceTransactionManager">
        <property name="dataSource" ref="dataSource" />
    </bean>

    <tx:advice id="txAdvice" transaction-manager="txManager">
        <tx:attributes>
            <tx:method name="*" />
        </tx:attributes>
    </tx:advice>

    <aop:config>
        <aop:pointcut id="allServices"
            expression="execution(* .service.impl.*.*(..))" />
        <aop:advisor advice-ref="txAdvice" pointcut-ref="allServices" />
    </aop:config>


<bean id="txManager2"
        class="org.springframework.jdbc.datasource.DataSourceTransactionManager">
        <property name="dataSource" ref="otherDataSource" />
    </bean>

    <tx:advice id="txAdvice2" transaction-manager="txManager2">
        <tx:attributes>
            <tx:method name="*" />
        </tx:attributes>
    </tx:advice>

    <aop:config>
        <aop:pointcut id="allOtherServices"
            expression="execution(* .service2.impl.*.*(..))" />
        <aop:advisor advice-ref="txAdvice2" pointcut-ref="allOtherServices" />
    </aop:config>

如何实现在其自己事务中运行persistOneByOne()?对于单行发生.if异常回滚。

EN

回答 1

Stack Overflow用户

发布于 2016-07-02 00:12:58

我认为您的场景适合基于保存点的数据库交互。Spring通过NESTED传播来支持它。

如果将嵌套传播建议应用于代码中的persistOneByOne()方法,那么每次执行该方法时,它都会创建一个保存点,如果发生异常,它将回滚到最后一个保存点。然后继续下一步。

从技术上讲,您也可以通过将REQUIRES_NEW传播建议应用于您的方法来做到这一点,但是它会在每次使用called.It时打开一个新事务,这被认为是一种糟糕的做法,因为它会在大量事务的情况下颠覆您的数据库。

您可以查看以下内容以了解更多详细信息:http://www.marcobehler.com/make-it-so-java-db-connections-and-transactions-html/spring-transactional-propagation-propagation-nested.html

此外,您还可以从txManager2的配置中删除事务通知,然后使用@Transactional注释来注释方法/类,而不是使用transactionManager注释。文档:http://docs.spring.io/spring/docs/current/javadoc-api/org/springframework/transaction/annotation/Transactional.html

您需要在配置中添加以下内容:

代码语言:javascript
复制
<tx:annotation-driven proxy-target-class="true"/>

这样,你的类看起来就像这样:

代码语言:javascript
复制
public class DataSource2OtherServiceClass{

     @Transactional(rollbackFor = {Exception.class}, propagation=PROPAGATION.REQUIRES_NEW, transactionManager="txManager2")
     public void prepareAndPeristData(){
         try{
            for(int i=0;i<10;i++)
              {
            // pre processing before persisting a single record
            persistOneByOne();
              }
            }catch (Exception e){
               log.error("Error occurred.. so didn't persist record as expected"};
            }

     @Transactional(rollbackFor = {Exception.class}, propagation=PROPAGATION.NESTED, transactionManager="txManager2")
     public void persistOneByOne()
       {
          dao.persist();
       } 
}
票数 0
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/37988583

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档