Jpa手动提交事务

Jpa事务手动提交

原因:jpa自带缓存,在开启事务的时候,不管是调用save还是saveAndFlush方法,需要保存的数据是不会直接进入数据库,而是会进入到jpa的缓存,只有当前事务结束后,事务才会commit进入数据库。这样的缓存机制保证了jpa可以在发生错误后正常的执行回滚操作。但是,总有一些情况下,对于一个方法里面的操作,有需要手动提交jpa事务以确保不管这个方法成功与否,这个子事务必须执行成功的情况。这种情况下就需要手动提交jpa事务。

jpa手动提交事务的实现

思路:自定义一个TransactionService,用于jpa手动提交事务。

TransactionService.java实现,代码如下:

public interface TransactionService {

    void begin();

    void commit();

    void rollback();

    /**
     * 在事务中执行回调函数
     * 谨慎使用
     * @param callable 回调函数
     */
    <V> V execute(Callable<V> callable);

}

TransactionServiceImpl.java实现,代码如下:

@Service
public class TransactionServiceImpl implements TransactionService {

    @Autowired
    private PlatformTransactionManager transactionManager;

    private ThreadLocal<TransactionStatus> threadLocal = new ThreadLocal<>();

    @Override
    public void begin() {
        // TransactionDefinition.PROPAGATION_REQUIRES_NEW 新开一个事务
        TransactionDefinition transactionDefinition =
                new DefaultTransactionDefinition(TransactionDefinition.PROPAGATION_REQUIRES_NEW);
        threadLocal.set(transactionManager.getTransaction(transactionDefinition));
    }

    @Override
    public void commit() {
        transactionManager.commit(threadLocal.get());
        threadLocal.remove();
    }

    @Override
    public void rollback() {
        transactionManager.rollback(threadLocal.get());
        threadLocal.remove();
    }

    @Override
    public <V> V execute(Callable<V> callable) {
        try {
            begin();
            V result = callable.call();
            commit();
            return result;
        } catch (Exception e) {
            rollback();
            throw new RuntimeException(e);
        }
    }
}

TransactionServiceImpl使用方法,其中xxxRepository是jpa的repository

xxxType save = transactionService.execute(() -> xxxRepository.saveAndFlush(object));

注意事项

  1. TransactionServiceImpl中的transactionManager应该是JpaTransactionManager,如果不是jpa那就使用对应的PlatformTransactionManager,例如HibernateTransactionManager,JtaTransactionManager等。

  2. 定义子事务的时候使用的是TransactionDefinition.PROPAGATION_REQUIRES_NEW,代表总是开始一个新事务。如果当前有事务,则该事务挂起。如果使用默认的TransactionDefinition.PROPAGATION_REQUIRED,会导致在有事务的情况下,子事务共享旧的事务,不会起到强制手动提交事务的效果。其他子事务的定义类型,参考:https://docs.spring.io/spring-framework/docs/current/javadoc-api/org/springframework/transaction/TransactionDefinition.html

  3. 谨慎使用这个强制提交事务,他会使得jpa回滚失效(对于子事务的部分回滚失效)

posted @ 2022-08-25 17:40  原生态咬死他  阅读(1118)  评论(0)    收藏  举报