JPA Repository含Bs1100Not方法启动报StackOverflowError,本地正常
问题分析与解决
问题场景
Repository定义:
@Repository public interface BooksForHealthPolicyRepository extends JpaRepository<BooksForHealthPolicy, BooksForHealthPolicyId>{ public List<BooksForHealthPolicy> findByCollectionDateGreaterThanEqualAndCollectionDateLessThanEqualAndProductCodeAndProductSubCodeAndBs1100Not(int collectionStartDate,int collectionEndDate, int productCode, int productSubCode,char bs1100); }
实体类对应字段:
@Column(name = "BS1100", nullable = false, length = 1) private char bs1100;
服务启动时抛出错误:
Exception: java.lang.StackOverflowError org.hibernate.hql.internal.ast.util.JoinProcessor.doFindAllNodes(JoinProcessor.java:116) org.hibernate.hql.internal.ast.util.JoinProcessor.doFindAllNodes(JoinProcessor.java:120) org.hibernate.hql.internal.ast.util.JoinProcessor.doFindAllNodes(JoinProcessor.java:120) org.hibernate.hql.internal.ast.util.JoinProcessor.doFindAllNodes(JoinProcessor.java:120) org.hibernate.hql.internal.ast.util.JoinProcessor.doFindAllNodes(JoinProcessor.java:120) org.hibernate.hql.internal.ast.util.JoinProcessor.doFindAllNodes(JoinProcessor.java:120) org.hibernate.hql.internal.ast.util.JoinProcessor.doFindAllNodes(JoinProcessor.java:120) org.hibernate.hql.internal.ast.util.JoinProcessor.doFindAllNodes(JoinProcessor.java:120) org.hibernate.hql.internal.ast.util.JoinProcessor.doFindAllNodes(JoinProcessor.java:120) org.hibernate.hql.internal.ast.util.JoinProcessor.doFindAllNodes(JoinProcessor.java:120)
本地运行正常,部署后启动失败,怀疑和Not关键字有关。
原因分析
- 依赖版本差异:本地与部署环境的Hibernate/Spring Data JPA版本不一致,旧版本在解析
Not关键字搭配char类型字段时,存在递归解析的bug,触发栈溢出。 - char类型兼容性问题:JPA对基本类型
char的解析支持不如包装类型Character,加上Not关键字后,HQL解析器陷入无限递归逻辑。
解决方法
方法一:替换Not为标准写法IsNot
Spring Data JPA的查询命名规范中,IsNot是更稳定的否定写法,部分旧版本Hibernate对该写法的解析逻辑更完善:
List<BooksForHealthPolicy> findByCollectionDateGreaterThanEqualAndCollectionDateLessThanEqualAndProductCodeAndProductSubCodeAndBs1100IsNot(int collectionStartDate, int collectionEndDate, int productCode, int productSubCode, char bs1100);
方法二:用@Query手写HQL绕开自动解析
直接编写查询语句,避免方法名自动解析的问题:
@Query("SELECT b FROM BooksForHealthPolicy b WHERE b.collectionDate >= :start AND b.collectionDate <= :end AND b.productCode = :code AND b.productSubCode = :subCode AND b.bs1100 != :bs1100") List<BooksForHealthPolicy> findFilteredBooks( @Param("start") int collectionStartDate, @Param("end") int collectionEndDate, @Param("code") int productCode, @Param("subCode") int productSubCode, @Param("bs1100") char bs1100);
方法三:将实体类字段改为Character包装类型
把基本类型char换成包装类型,提升JPA解析的兼容性:
@Column(name = "BS1100", nullable = false, length = 1) private Character bs1100;
同时更新Repository方法的参数类型为Character。
方法四:统一本地与部署环境的依赖版本
检查Maven的pom.xml或Gradle的build.gradle,确保部署环境的Spring Data JPA、Hibernate版本和本地完全一致,消除版本差异带来的解析bug。
内容的提问来源于stack exchange,提问作者msadasjwd
相关产品推荐
相关产品推荐

