Spring Data 2.0.6访问HibernateProxy懒加载关联时抛异常求助
解决Spring Data + Hibernate懒加载代理导致的PersistentEntity找不到异常
我之前在类似版本组合里碰到过一模一样的问题,本质是Spring Data没办法识别Hibernate生成的懒加载代理类,误把代理类当成了实体类去查找对应的PersistentEntity,所以抛出了那个异常。下面给你几个实用的解决办法:
方法一:手动解包Hibernate代理
在访问关联对象或者把代理对象传给Spring Data方法之前,先用Hibernate的工具类解包,拿到实际的实体对象:
// 假设你的关联对象是Service类型 Workspace workspace = workspaceRepository.findById(1L).orElseThrow(); // 解包代理,获取真实实体 Service actualService = (Service) Hibernate.unproxy(workspace.getService()); // 之后用actualService进行操作就不会有问题了
这个方法简单直接,适合临时解决单个场景的问题。
方法二:配置Spring Data自动解包代理
如果不想每次都手动解包,可以自定义Spring Data的Repository工厂,让它自动识别并解包Hibernate代理:
首先创建自定义的RepositoryFactoryBean和Factory:
public class CustomJpaRepositoryFactoryBean<T extends Repository<S, ID>, S, ID> extends JpaRepositoryFactoryBean<T, S, ID> { public CustomJpaRepositoryFactoryBean(Class<? extends T> repositoryInterface) { super(repositoryInterface); } @Override protected RepositoryFactorySupport createRepositoryFactory(EntityManager entityManager) { return new CustomJpaRepositoryFactory(entityManager); } private static class CustomJpaRepositoryFactory extends JpaRepositoryFactory { public CustomJpaRepositoryFactory(EntityManager entityManager) { super(entityManager); } @Override protected PersistentEntity<?, ?> getPersistentEntity(Class<?> domainClass) { // 解包代理类,获取真实的实体类 Class<?> actualDomainClass = HibernateProxyHelper.getClassWithoutInitializingProxy(domainClass); return super.getPersistentEntity(actualDomainClass); } } }
然后在你的JPA配置类里指定这个自定义的FactoryBean:
@Configuration @EnableJpaRepositories( basePackages = "com.yourproject.repository", repositoryFactoryBeanClass = CustomJpaRepositoryFactoryBean.class ) public class JpaConfiguration { // 你的EntityManagerFactory等配置... }
这样所有Spring Data的Repository操作都会自动处理代理类,不用再手动解包了。
方法三:升级版本解决兼容性问题
你用的Spring Data 2.0.6和Hibernate 5.3.0.CR2都是比较旧的版本,而且Hibernate的CR2是候选版本,可能存在兼容性bug。建议升级到:
- Spring Data JPA 2.1.x及以上版本
- Hibernate 5.3.x的正式版(比如5.3.20.Final)
升级后官方可能已经修复了代理类识别的问题,从根源上解决这个异常。
另外也可以检查下你的实体映射,确保@ManyToOne的配置没有问题,比如显式指定targetEntity属性(虽然大多数情况下不需要,但有时候能帮Hibernate更准确识别关联类型):
@ManyToOne(fetch = FetchType.LAZY, targetEntity = Service.class) @JoinColumn(name = "SERVICE_ID", nullable = false, insertable = false, updatable = false) private Service service;
内容的提问来源于stack exchange,提问作者Nathan Coast
相关产品推荐
相关产品推荐

