繁体   English   中英

Spring Transaction没有回滚

[英]Spring Transaction not rolling back

我有这样的事情:

@Service
@Transactional
public class ServiceA {

    @Autowired
    SomeDAO1 dao1; 

    @Autowired
    ServiceB serviceB;

    public void methodServiceA() {

        serviceB.someMethodThatRunsInsertIntoDB(); 
        dao1.anotherMethodThatRunsInsertIntoDB(); 

    }

}

@Service
@Transactional
public class ServiceB {

     @Autowired
     Dao2 dao2;

     public void someMethodThatRunsInsertIntoDB() {
          dao2.insertXXX();
     }

}

我的问题是:如果serviceB.someMethodThatRunsInsertIntoDB()执行成功但dao1.anotherMethodThatRunsInsertIntoDB()抛出异常,则不会回滚serviceB所做的更改。 如果在dao1.anotherMethodThatRunsInsertIntoDB()发生异常,我需要回滚这些更改。 我怎样才能做到这一点?

//已编辑

spring-servlet.xml中的事务配置

<bean id="transactionManager" class="org.springframework.orm.jpa.JpaTransactionManager">
    <property name="entityManagerFactory" ref="entityManagerFactory" />
    <property name="jpaDialect">
        <bean class="org.springframework.orm.jpa.vendor.HibernateJpaDialect" />
    </property>
</bean>

如果一个dao使用EntityManager而另一个dao使用JdbcTemplate与DB交互是否相关?

// UPDATE - EntityManager配置

<bean id="entityManagerFactory" class="org.springframework.orm.jpa.LocalContainerEntityManagerFactoryBean">
    <property name="dataSource" ref="dataSource" />
    <property name="jpaVendorAdapter">
        <bean class="org.springframework.orm.jpa.vendor.HibernateJpaVendorAdapter">
            <property name="showSql" value="true" />
            <property name="generateDdl" value="true" />
        </bean>
    </property>

你需要传递rollbackFor参数与您检查的异常的类型。 看起来Spring默认只在未经检查的异常上回滚。 更多细节: Spring事务:在Exception或Throwable上回滚

你需要在spring配置文件中使用<tx:annotation-driven/>来启用注释驱动的事务管理。

这是因为您的dao1.anotherMethodThatRunsInsertIntoDB()调用不支持当前事务(ServiceA事务)。

您需要在ServiceB类中使用低于传播级别。

@Service
@Transactional(propagation = Propagation.REQUIRED)
public class ServiceB {

要求: Spring REQUIRED行为意味着如果当前bean方法执行上下文中已经打开的事务,将使用相同的事务。 如果不存在,则创建一个新的。 简而言之,这意味着如果内部(第二个事务)方法导致事务回滚,则外部(第一个事务)方法将无法提交并且还将回滚事务。

传播方式:通常,在事务范围内执行的所有代码都将在该事务中运行。 但是,您可以选择在事务上下文已存在时执行事务方法时指定行为。 例如,代码可以继续在现有事务中运行(常见情况); 或者可以暂停现有交易并创建新交易。 Spring提供了EJB CMT中熟悉的所有事务传播选项。 要阅读有关Spring中事务传播的语义,请参阅事务传播

编辑
注意:默认情况下,将事务设置为回滚状态的唯一例外是未经检查的异常(如RuntimeException)。 如果您希望已检查的异常也将事务设置为回滚,则必须将它们配置为执行此操作,例如。

@Service
@Transactional(propagation = Propagation.REQUIRED, rollbackFor = YourCheckedException.class))
public class ServiceA {

注意:正如我所注意到的,声明式事务管理是基于AOP的。 这意味着Spring将事务bean包装到事务代理中,该代理负责启动和提交事务。 这意味着必须由代理拦截方法调用才能成为事务性的。 您需要在Spring配置文件中确保以下配置。

<tx:annotation-driven transaction-manager="transactionManager" />

我的第一个建议是在方法级别使用@Transactional注释,如果在类级别上真的不需要它。

第二件事,尝试使用javax.transaction.Transactional注释而不是org.springframework.transaction.annotation.Transactional ,Spring会自动处理传播。

您还需要在使用@Transactional之前启用事务管理,使用Spring Boot我们可以通过@EnableTransactionManagement标记Application类来@EnableTransactionManagement

但是,如果您愿意,您也可以通过XML配置( <tx:annotation-driven /> )来完成此操作。 阅读http://docs.spring.io/spring-data/jpa/docs/1.11.0.M1/reference/html/#transactions了解更多详情

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM