代理实现事物的坑
前言说明
代码中使用注解式事务,类内部方法调用导致没有被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失效的场景请参见