使用QueryDSL时出现JPA错误:java.lang.NoSuchFieldError: LIKE_IC
我之前也踩过QueryDSL这个NoSuchFieldError的坑,结合实际解决经验,给你几个可行的方案:
先看你给出的错误日志:
2018-05-01 13:18:38.517 DEBUG 372 --- [nio-8080-exec-1] o.s.b.c.web.OrderedRequestContextFilter : 已清除线程绑定的请求上下文:org.apache.catalina.connector.RequestFacade@308cc4e8
2018-05-01 13:18:38.520 ERROR 372 --- [nio-8080-exec-1] o.a.c.c.C.[.[.[.[dispatcherServlet] : 路径[/boot]上下文内的servlet [dispatcherServlet]的Servlet.service()抛出异常[Handler处理失败;嵌套异常为java.lang.NoSuchFieldError...]
这个错误本质是JVM加载类时找不到预期的字段,最常见的原因就是依赖版本不兼容或者依赖冲突,尤其是QueryDSL和Spring Data JPA、Hibernate这些框架的版本没对齐,或者项目里同时存在多个版本的QueryDSL jar包。
1. 对齐QueryDSL与Spring生态的版本
QueryDSL和Spring Boot/Spring Data的版本有严格对应关系,乱指定版本很容易出问题:
- 如果是Spring Boot 1.5.x系列,建议用QueryDSL 4.x版本
- 如果是Spring Boot 2.x及以上,对应QueryDSL 5.x或更高版本(具体可以参考Spring Boot官方的依赖管理清单)
举个Maven配置的例子,确保所有QueryDSL相关依赖版本一致:
<dependencies> <!-- QueryDSL JPA依赖 --> <dependency> <groupId>com.querydsl</groupId> <artifactId>querydsl-jpa</artifactId> <version>5.0.0</version> </dependency> <!-- 用于生成Q类的APT依赖 --> <dependency> <groupId>com.querydsl</groupId> <artifactId>querydsl-apt</artifactId> <version>5.0.0</version> <scope>provided</scope> </dependency> </dependencies>
如果用Spring Boot的话,最好直接用starter或者依赖管理来自动对齐版本,避免手动指定版本号导致的不兼容。
2. 排查并解决依赖冲突
项目里可能有其他依赖间接引入了旧版本的QueryDSL,导致版本冲突。你可以用以下命令查看依赖树:
- Maven:
mvn dependency:tree - Gradle:
./gradlew dependencies
找到重复的QueryDSL依赖后,在引入该依赖的地方排除掉旧版本,比如Maven里的排除配置:
<dependency> <groupId>第三方依赖组ID</groupId> <artifactId>第三方依赖ArtifactID</artifactId> <exclusions> <exclusion> <groupId>com.querydsl</groupId> <artifactId>querydsl-core</artifactId> </exclusion> <!-- 如果有其他冲突的QueryDSL模块,也一起排除 --> </exclusions> </dependency>
3. 清理重构项目,重新生成Q类
有时候旧的编译文件或者自动生成的Q类是用旧版本QueryDSL生成的,也会导致这个错误。执行以下操作:
- 清理项目构建产物:Maven用
mvn clean,Gradle用./gradlew clean - 重新构建并生成Q类:Maven用
mvn install,Gradle用./gradlew build - 如果是IDE开发,记得同步一下依赖并重新生成Q类(比如IntelliJ可以右键项目 -> Maven/Gradle -> Reload Project)
内容的提问来源于stack exchange,提问作者Harshal Patil

