转载

Spring JPA 事务只读与自动持久化

JPA Hibernate 框架中的实体entity有三种状态,transient(瞬时状态),persistent(持久化状态)以及detached(离线状态)自动持久化,本文主要是讨论持久化状态的一些细节问题。

如果一个实体entity通过query语句查出来后,调用实体相关的setXXX方法,有可能会被待久化到db中,也有可以不会,总体来说,关键点取决于setXXX方法所处的函数是否有事务(Session)包裹着,但到生产环境中,会有比较多的复杂情况,下面我们以声明式事务的实现方式来探讨,编程式事务主要就是手工对session和transaction的管理,与之类似,亦可借鉴。

1、单一业务,自动提交场景(主方法test有事务):

@Service
public class FunctionService {

    private Logger logger = LoggerFactory.getLogger(FunctionService.class);
    @Autowired
    private TUserServcie tUserServcie;
    @Autowired
    private TAddressServcie tAddressServcie;
    
    //测试方法
    @Transactional()
    public void test(String name){
        TUser user = tUserServcie.findByName(name);
        logger.info("test before age:"+user.getAge());
        user.setAge(user.getAge()+1);
    }
}

复制代码

2、单一业务,不会自动提交场景(主方法test不含事务事务或为read-only):

@Service
public class FunctionService {

    private Logger logger = LoggerFactory.getLogger(FunctionService.class);
    @Autowired
    private TUserServcie tUserServcie;
    @Autowired
    private TAddressServcie tAddressServcie;
    //测试方法
    //@Transactional(readOnly = true)
    public void test(String name){
        TUser user = tUserServcie.findByName(name);
        logger.info("test before age:"+user.getAge());
        user.setAge(user.getAge()+1);
    }
}

复制代码

3、复合业务,不会自动提交(test无事务或read-only且countAllNotTrans无事务或read-only)

@Service
public class FunctionService {
    private Logger logger = LoggerFactory.getLogger(FunctionService.class);
    @Autowired
    private TUserServcie tUserServcie;
    @Autowired
    private TAddressServcie tAddressServcie;
    
    //测试方法
    //@Transactional(readOnly = true)
    public void test(String name){
        TUser user = tUserServcie.findByName(name);
        logger.info("test before age:"+user.getAge());
        user.setAge(user.getAge()+1);
        tAddressServcie.countAll();
    }
}

@Service
public class TAddressServcie {
    @Autowired
    private TAddressRepo tAddressRepo;
    
    //@Transactional(readOnly = true)
    public int countAll (){
        return tAddressRepo.countAll();
    }
}

public interface TAddressRepo extends JpaRepository<TAddress, Integer> {
    @Query(value ="SELECT count(*) FROM TAddress")
    int countAll();
}
复制代码

4、特别注意!!!复合业务,会自动提交(test无事务,countAll有事务)

@Service
public class FunctionService {
    private Logger logger = LoggerFactory.getLogger(FunctionService.class);
    @Autowired
    private TUserServcie tUserServcie;
    @Autowired
    private TAddressServcie tAddressServcie;
    //测试方法
    public void test(String name){
        TUser user = tUserServcie.findByName(name);
        logger.info("test before age:"+user.getAge());
        user.setAge(user.getAge()+1);
        tAddressServcie.countAll();
    }
}

@Service
public class TAddressServcie {
    @Autowired
    private TAddressRepo tAddressRepo;
    
    @Transactional()
    public int countAll (){
        return tAddressRepo.countAll();
    }
}

public interface TAddressRepo extends JpaRepository<TAddress, Integer> {
    @Query(value ="SELECT count(*) FROM TAddress")
    int countAll();
}
复制代码
原文  https://juejin.im/post/5cff5fb15188251346598eeb
正文到此结束
Loading...