学习Spring和Hibernate遇两类异常:控制器代理及事务问题求助
嘿,这俩问题都是Spring+Hibernate整合时的高频坑,我来给你拆解下解法:
问题1:IllegalStateException——映射的控制器方法类XXX不是实际控制器Bean实例'com.sun.proxy.$Proxy55'的实例
原因分析
这个问题本质是Spring动态代理的类型不匹配。默认情况下Spring用JDK动态代理,它是基于接口生成代理类的——也就是说,你的控制器如果是个普通类(没实现接口),Spring生成的代理对象其实是一个实现了控制器所有接口的代理类(就是你看到的com.sun.proxy.$Proxy55),而不是原控制器类的子类。这时候如果你用原控制器的类类型去做类型判断、注入或者强转,就会抛出这个异常。
解决办法
我给你两个常用的方案,选哪个看你的项目情况:
- 方案一:让控制器实现接口
给你的控制器类定义一个对应的接口,把所有控制器方法都放到接口里,然后在注入、类型判断的时候用接口类型而不是具体的控制器类类型。比如原来用@Autowired private XXXController controller;改成@Autowired private XXXControllerInterface controller; - 方案二:强制Spring用CGLIB代理
如果不想改代码加接口,就配置Spring使用CGLIB代理(基于类的代理),这样生成的代理类是原控制器类的子类,就能和原类类型匹配了:- 注解配置:在启动类或者配置类上加上
@EnableAspectJAutoProxy(proxyTargetClass = true) - XML配置:如果是XML配置的项目,添加
<aop:aspectj-autoproxy proxy-target-class="true"/>
- 注解配置:在启动类或者配置类上加上
问题2:HibernateException——getCriteriaBuilder在无活动事务时无效
原因分析
这个错误很明确:你调用getCriteriaBuilder()的时候,当前Hibernate Session没有绑定到一个活动的事务里。Hibernate的很多操作(比如查询、修改)都需要在事务上下文执行,要么是你没开启事务,要么是Spring的事务管理没生效,导致Session处于无事务状态。
解决办法
按这几步排查,基本能解决:
- 第一步:确保事务注解生效
在你的业务方法(或者DAO方法)上加上@Transactional注解,同时要保证Spring已经启用了事务管理:- 注解项目:在配置类上添加
@EnableTransactionManagement - XML项目:配置
<tx:annotation-driven/>
- 注解项目:在配置类上添加
- 第二步:检查Session获取方式
如果你是手动获取Session,别用sessionFactory.openSession(),改用sessionFactory.getCurrentSession()——getCurrentSession()会自动绑定到当前Spring管理的事务,而openSession()是创建新Session,需要你手动开启/提交事务。 - 第三步:确认事务管理器配置正确
要确保Spring的事务管理器是针对Hibernate的,比如配置HibernateTransactionManager并关联你的SessionFactory:@Bean public HibernateTransactionManager transactionManager(SessionFactory sessionFactory) { HibernateTransactionManager txManager = new HibernateTransactionManager(); txManager.setSessionFactory(sessionFactory); return txManager; }
我之前碰到第二个问题的时候,一开始以为是Hibernate的Session配置错了,折腾半天发现是业务类没加@Transactional,事务根本没启动,你可以先检查这个点!
内容的提问来源于stack exchange,提问作者Дмитрий Стеба
相关产品推荐
相关产品推荐

