Spring Boot中的事务配置失败

时间:2018-01-05 13:57:22

标签: spring-boot spring-transactions

更新

我发现我将A类注入C类,扩展了一个外部类, 那个班不是春天管理的,就像这样:

public class C extends ExternalClass {    
    @AutoWired
    private A a;
    //doSomething...    
}

这应该是交易失败的主要原因。

另一个问题:是否有任何方法可以使A类的Spring管理事务注入到未由spring处理的anothor类中?

我正在使用Spring Boot和Mybatis构建一个项目。

我遇到一个问题,即某个服务类不能创建事务连接,也不会执行回滚。

我发现如果我在B类中删除了A类的注射,就像这样:

class A{
    //@Autowired
    //private B b;
    // b is not used in this class
    @Autowired
    private ADao dao;
}

class B{
    @Autowired 
    private BDao dao;

    //Transaction of this method failed
    //session didn't roll back
     public void (){
          dao.insert(new Entity ());
          //Exception here
     }
}

B类创建的连接是事务性的。两个类都在同一个包中,但如果我添加该注入,则事务将失败。令我困惑的是,B级可以注入其他类,交易也可以很好地运作。

这是日志:

2018-01-05 21:30:33.861 DEBUG 10346 --- [http-nio-8099-exec-2] org.mybatis.spring.SqlSessionUtils       97 : Creating a new SqlSession
2018-01-05 21:30:33.866 DEBUG 10346 --- [http-nio-8099-exec-2] org.mybatis.spring.SqlSessionUtils       148 : SqlSession [org.apache.ibatis.session.defaults.DefaultSqlSession@3aeb5ca8] was not registered for synchronization because synchronization is not active
2018-01-05 21:30:33.888 DEBUG 10346 --- [http-nio-8099-exec-2] o.s.jdbc.datasource.DataSourceUtils      110 : Fetching JDBC Connection from DataSource
2018-01-05 21:30:33.888 DEBUG 10346 --- [http-nio-8099-exec-2] o.s.j.d.DriverManagerDataSource          142 : Creating new JDBC DriverManager Connection to [jdbc:mariadb://localhost:3306/test?useUnicode=true&characterEncoding=UTF-8&allowMultiQueries=true]
2018-01-05 21:30:33.905 DEBUG 10346 --- [http-nio-8099-exec-2] o.m.s.t.SpringManagedTransaction         87 : JDBC Connection [org.mariadb.jdbc.MySQLConnection@2bad8689] will not be managed by Spring
2018-01-05 21:30:33.908 DEBUG 10346 --- [http-nio-8099-exec-2] p.c.z.admin.dao.UserDao.insertSelective  159 : ==>  Preparing: INSERT INTO sys_user ( id,username ) VALUES( ?,? ) 
2018-01-05 21:30:33.916 DEBUG 10346 --- [http-nio-8099-exec-2] p.c.z.admin.dao.UserDao.insertSelective  159 : ==> Parameters: null, test(String)
2018-01-05 21:30:33.929 DEBUG 10346 --- [http-nio-8099-exec-2] p.c.z.admin.dao.UserDao.insertSelective  159 : <==    Updates: 1
2018-01-05 21:30:33.932 DEBUG 10346 --- [http-nio-8099-exec-2] p.c.z.a.d.U.insertSelective!selectKey    159 : ==>  Executing: SELECT LAST_INSERT_ID() 
2018-01-05 21:30:33.940 DEBUG 10346 --- [http-nio-8099-exec-2] p.c.z.a.d.U.insertSelective!selectKey    159 : <==      Total: 1
2018-01-05 21:30:33.942 DEBUG 10346 --- [http-nio-8099-exec-2] org.mybatis.spring.SqlSessionUtils       191 : Closing non transactional SqlSession [org.apache.ibatis.session.defaults.DefaultSqlSession@3aeb5ca8]

我尝试了3种配置事务的方法:

使用java config:

@Bean(name = "transactionInterceptor")
public TransactionInterceptor transactionInterceptor(PlatformTransactionManager platformTransactionManager) {
    TransactionInterceptor transactionInterceptor = new TransactionInterceptor();
    transactionInterceptor.setTransactionManager(platformTransactionManager);
    Properties transactionAttributes = new Properties();
    transactionAttributes.setProperty("insert*","PROPAGATION_REQUIRED,-Throwable");
    transactionAttributes.setProperty("update*","PROPAGATION_REQUIRED,-Throwable");
    transactionAttributes.setProperty("delete*","PROPAGATION_REQUIRED,-Throwable");
    transactionAttributes.setProperty("select*","PROPAGATION_REQUIRED,-Throwable,readOnly");
    transactionInterceptor.setTransactionAttributes(transactionAttributes);
    return transactionInterceptor;
}

@Bean
public BeanNameAutoProxyCreator transactionAutoProxy() {
    BeanNameAutoProxyCreator transactionAutoProxy = new BeanNameAutoProxyCreator();
    transactionAutoProxy.setProxyTargetClass(true);
    transactionAutoProxy.setBeanNames("*ServiceImpl");
    transactionAutoProxy.setInterceptorNames("transactionInterceptor");
    return transactionAutoProxy;
}

和xml:

<tx:advice id="txAdvice" transaction-manager="transactionManager">
    <tx:attributes>
        <tx:method name="save*" propagation="REQUIRED"/>
        <tx:method name="del*" propagation="REQUIRED"/>
        <tx:method name="update*" propagation="REQUIRED"/>
        <tx:method name="insert*" propagation="REQUIRED"/>
        <tx:method name="*" rollback-for="Exception"/>
    </tx:attributes>
</tx:advice>

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

和@Transactional。 然而,他们都没有工作。

1 个答案:

答案 0 :(得分:0)

问题是如果将一个类注入另一个不是spring托管bean的类,那么spring transaction管理将失败。 因此,在发生事务失败时,请检查是否存在错误的依赖注入。