关于PROPAGATION_REQUIRES_NEW和PROPAGATION_NESTED事务的比较

最近在用spring-data-jpa做事务处理时,由于两个事务都处理了同一个表,其中一个事务加锁,另外一个事务不加锁,于是在调用的另外一个事务中使用了嵌套的方式,但是运行却报
JpaDialect does not support savepoints - check your JPA provider's capabilities

后经查实,原来Hibernate/JPA并不能实现嵌套事务,嵌套事务仅仅在JDBC级别支持,对于Hibernate/JPA要实现嵌套事务,也仅仅在dialect为Oracle的情况下才完全实现。

那怎么办?那当然是使用JDBC事务控制咯,因此你可以使用JdbcTemplate或者mybatis数据库框架进行控制。

<tx:annotation-driven  transaction-manager="transactionManager"/>   
<bean id="jdbcTemplate" class="org.springframework.jdbc.core.JdbcTemplate">  
    <property name="dataSource" ref="dataSource"></property>  
</bean>

这个时候,只需要在方法上添加@Transactional(propagation=Propagation.NESTED)注解或者在aop配置切面即可。

那么,为什么不用REQUIRES_NEW呢,这两者有什么不同?

PROPAGATION_REQUIRES_NEW starts a new, independent "inner" transaction for the given scope. This transaction will be committed or rolled back completely independent from the outer transaction, having its own isolation scope, its own set of locks, etc. The outer transaction will get suspended at the beginning of the inner one, and resumed once the inner one has completed. ... 
PROPAGATION_NESTED on the other hand starts a "nested" transaction, which is a true subtransaction of the existing one. What will happen is that a savepoint will be taken at the start of the nested transaction. Íf the nested transaction fails, we will roll back to that savepoint. The nested transaction is part of of the outer transaction, so it will only be committed at the end of of the outer transaction.
按字面上的理解就是,requires_new是独立的,运行的时候自己提交,不受外部事务调用的控制;而nested,顾名思义,“嵌套的”,即存在外部事务时,会作为外部事务的一部分,自身发生异常将连带外部事务进行回滚。





你可能感兴趣的:(spring,Hibernate,jpa,transaction)