Spring的事务传播所需,REQUIRES_NEW(Spring Transaction prop

2019-08-19 07:25发布

在下面的代码方法doService1()更新正确的SQL,但doService2() SQL有一些问题,但是当我打电话doService()它必须提交doService1()更新数据库,即使doService2()有一个sql exception ,因为doService2()REQUIRES_NEW Propagation类型,但是当我尼姑这doService1()更新不提交DB ..

@Service public class DbClass {

      static Logger log = Logger.getLogger(
              DbClass.class.getName());

@Autowired
private DataSource dataSource;

@Transactional(propagation=Propagation.REQUIRED)
public void doService(){
    doService1();
    doService2();
}

@Transactional(propagation=Propagation.REQUIRED)
public void doService1(){
    JdbcTemplate jdbcTemplate = new JdbcTemplate(dataSource);
    String sql = "  update BATCHJOBSTATUS set PROCESSINGDATE = '20130322'  " ;
    int rowCount1 =  jdbcTemplate.update(sql);
    System.out.println(" rowCount1 >" + rowCount1);
}

@Transactional(propagation=Propagation.REQUIRES_NEW)
public void doService2(){
    JdbcTemplate jdbcTemplate = new JdbcTemplate(dataSource);
    String sql = "  update aa set a_name = 'hhh' where a_id = 4 and " ;
    int rowCount1 =  jdbcTemplate.update(sql);
    System.out.println(" rowCount2 >" + rowCount1);
}   
}

在下面的方式很好,但仍然面临着同样的问题,你的球员的建议测试。 在这里,我doService2()在一个单独的类,但即使仍然有同样的问题,上述

@Service
public class DbClass {

  static Logger log = Logger.getLogger(
          DbClass.class.getName());

@Autowired
private DataSource dataSource;

@Autowired
private DbClass2 dbClass2;

@Transactional
public void doService(){
    doService1();
    dbClass2.doService2();
}

@Transactional(propagation=Propagation.REQUIRED )
public void doService1(){
    JdbcTemplate jdbcTemplate = new JdbcTemplate(dataSource);
    String sql = "  update BATCHJOBSTATUS set PROCESSINGDATE = '20130322'  " ;
    int rowCount1 =  jdbcTemplate.update(sql);
    System.out.println(" rowCount1 >" + rowCount1);

    }


}


@Service
public class DbClass2 {


@Autowired
private DataSource dataSource;

@Transactional(propagation=Propagation.REQUIRES_NEW)
public void doService2() {
    System.out.println("*******doService2*********`");

    JdbcTemplate jdbcTemplate = new JdbcTemplate(dataSource);

    String sql = "  update aa set a_name = 'hhh' where a_id_ = 4  " ;

    int rowCount2 =  jdbcTemplate.update(sql);

    System.out.println(" rowCount2 >" + rowCount2);

}

}



<beans xmlns="http://www.springframework.org/schema/beans"
    xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
    xmlns:context="http://www.springframework.org/schema/context"
    xmlns:oxm="http://www.springframework.org/schema/oxm"
         xmlns:aop="http://www.springframework.org/schema/aop"
     xmlns:tx="http://www.springframework.org/schema/tx"

    xsi:schemaLocation="http://www.springframework.org/schema/beans
        http://www.springframework.org/schema/beans/spring-beans-3.0.xsd
             http://www.springframework.org/schema/tx 
     http://www.springframework.org/schema/tx/spring-tx-3.0.xsd
     http://www.springframework.org/schema/aop 
     http://www.springframework.org/schema/aop/spring-aop-3.0.xsd

        http://www.springframework.org/schema/context
        http://www.springframework.org/schema/context/spring-context-3.0.xsd
        http://www.springframework.org/schema/oxm http://www.springframework.org/schema/oxm/spring-oxm-3.0.xsd">


    <context:annotation-config />

    <context:component-scan base-package="com.spring"/>

      <tx:annotation-driven transaction-manager="txManager1" proxy-target-class="true"/>



    <bean id="dataSource" class="org.springframework.jdbc.datasource.DriverManagerDataSource">
        <property name="driverClassName" value="oracle.jdbc.driver.OracleDriver" />
        <property name="url" value="jdbc:oracle:thin:@192.168.8.121:1521:h3" />
        <property name="username" value="admin" />
        <property name="password" value="admin" />
    </bean>


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

    <bean id="batchJob" class="com.spring.jdbc.BatchJob">
    </bean>


</beans>

Answer 1:

我前面有同样的问题,这是解决了这里: 奇怪的行为与@Transactional(传播= Propagation.REQUIRES_NEW)

使用默认设置,不会有当你调用创建的任何新的事务代理doService2()同一类,因此你的注释是不是用户。

为了避免这个问题,你可以把doService2()另一个类,或者声明它像这样用AspectJ事务: <tx:annotation-driven transaction-manager="transactionManager" mode="aspectj"/>

最好的解决方案将取决于您的应用程序。 (这里的第二个似乎更合适)



Answer 2:

要将呼叫doService2()可能没有在其上运行,因为我假设你正在使用JDK动态代理(代理接口),而不是基于CGLIB代理任何交易建议。 如果你不已经知道如何工作,你可能需要阅读: http://static.springsource.org/spring/docs/3.0.x/reference/aop.html#aop-proxying 。

如果你不使用CGLIB(目标级代理),它永远不会通过Spring事务顾问去,当你调用doService2()因为它被调用的方法,而不是直接去透过包裹在春季启动时创建的为您服务。

你可以让你的例如通过移动工作doService2()不同的服务类,然后将其注入到该服务。 你会通过代理和交易的意见将被运行会这样。

否则,如果你准备让你的项目中较大的变化,你可以让你的榜样工作,因为-是:1)确保CGLIB是在类路径中,和2)打开proxy-target-class ,或力它使用CGLIB代理因此通过摆脱你的服务接口。

<tx:annotation-driven transaction-manager="transactionManager" proxy-target-class="true"/>

如果你要做到这一点,请确保你通过第一个链接:)阅读。



Answer 3:

根据春季文档 (检查节10.5.6.1),Spring框架事务将回滚只RuntimeException的
不为别的检查 excpetions喜欢SqlException 。 所以,如果你真的想为这个异常的回滚,你必须像下面指定它

@Transactional(propagation=Propagation.REQUIRES_NEW,rollbackFor=SQLException.class)
public void doService2(){
    JdbcTemplate jdbcTemplate = new JdbcTemplate(dataSource);
    String sql = "  update aa set a_name = 'hhh' where a_id = 4 and " ;
    int rowCount1 =  jdbcTemplate.update(sql);
    System.out.println(" rowCount2 >" + rowCount1);
}

试试这个,让我知道,如果它的工作原理。
同时此可能会帮助更多。



文章来源: Spring Transaction propagation REQUIRED, REQUIRES_NEW