代理实现事物的坑

前言说明

代码中使用注解式事务,类内部方法调用导致没有被AOP代理开启事务,导致报错:org.hibernate.HibernateException: createNativeQuery is not valid without active transaction

问题复现

源代码

public int getPreviousRentContractMonthRent(String houseSourceCode, Long roomId, String roomCode){
  this.getPreviousRentContrace(houseSourceCode, roomId, roomCode);
  if (CollectionUtils.isEmpty(rentContractList)) {
    return -1;
  } else {
    return  rentContractList.get(0).getMonthRent().intValue();
  }
}   

@FlexTransaction(sessionFactory = DataConstant.AMI_SESSION_FACTORY, dataSource = DataConstant.AMI_DATA_SOURCE)
public List<DWRentContractDO> getSalePriceOfCurrentRentContract(String rentContractCode, String roomCode, Long roomId) {
  // 查询
  Session session = getSessionFactory().getCurrentSession();
  NativeQuery nativeQuery = session.createNativeQuery(sql.toString());//这里报错

  //查询操作

}

解决办法

类内部方法调用时,需要使用获取代理再调用AmiDao proxy = (AmiDao)AopContext.currentProxy();

public int getPreviousRentContractMonthRent(String houseSourceCode, Long roomId, String roomCode){
  //需要用代理
  AmiDao proxy = (AmiDao)AopContext.currentProxy();
  List<DWRentContractDO> rentContractList = proxy.getPreviousRentContrace(houseSourceCode, roomId, roomCode);
  if (CollectionUtils.isEmpty(rentContractList)) {
    return -1;
  } else {
    return  rentContractList.get(0).getMonthRent().intValue();
  }
}

@FlexTransaction(sessionFactory = DataConstant.AMI_SESSION_FACTORY, dataSource = DataConstant.AMI_DATA_SOURCE)
public List<DWRentContractDO> getSalePriceOfCurrentRentContract(String rentContractCode, String roomCode, Long roomId) {
  // 查询
  Session session = getSessionFactory().getCurrentSession();
  NativeQuery nativeQuery = session.createNativeQuery(sql.toString());//问题解决

  //查询操作

}

总结

这里可以简单理解下,AOP底层是CGLIB实现的动态代理,当外部类调用被代理对象时,通过调用动态生成的代理类达到增强的效果,但是如果是方法内部调用,AOP是捕获不到的,也就出现了获取不到事务的情况。

@Transactional失效的场景请参见

posted @ 2020-05-20 16:40  蒙多~想去哪就去哪  阅读(113)  评论(0)    收藏  举报