JDK11下Querydsl @QueryInit(*.*)失效引发空指针异常
JDK11下Querydsl @QueryInit访问第三层嵌套属性触发NullPointerException问题
问题描述
项目从JDK8迁移至JDK11后,使用Querydsl的@QueryInit(*.*)注解时,前两层嵌套属性(SpeedViolation.fact1.car)可正常访问,但调用第三层属性vrp时抛出NullPointerException。该问题仅在JDK11环境下出现,JDK8环境运行完全正常。
相关代码
实体类代码
SpeedViolation类
@Document(collection = "speed_violation") @Getter @Setter @NoArgsConstructor @EqualsAndHashCode(callSuper = true) @ToString(callSuper = true) public class SpeedViolation { // ... @NotNull @QueryEmbedded @QueryInit("*.*") protected Fact fact1; // ... }
Fact类
@Data @EqualsAndHashCode(of = "id") @AllArgsConstructor @NoArgsConstructor @Builder public class Fact { // ... @QueryEmbedded private Car car; // ... }
Car类
@Data @NoArgsConstructor @AllArgsConstructor @Builder public class Car { @QueryEmbedded private Vrp vrp; }
Vrp类
@Data @NoArgsConstructor @AllArgsConstructor @EqualsAndHashCode(of = "number") @Builder public class Vrp { @NotNull private String number; }
业务使用代码
@Override public Optional<SpeedViolation> findPendingForFactViolation(String vrp, Long complexId, Long camera2Id, LocalDateTime secondFactPhotoDate, LocalDateTime maxFirstFactPhotoDate, LocalDateTime minFirstFactPhotoDate) { QSpeedViolation speedViolation = QSpeedViolation.speedViolation; // 此处访问vrp时抛出NullPointerException Predicate predicate = speedViolation.fact1.car.vrp.number.eq(vrp); // ... }
项目依赖配置(pom.xml)
<properties> <!-- ... --> <java.version>11</java.version> <spring-boot.version>2.1.6.RELEASE</spring-boot.version> <querydsl.version>4.2.2</querydsl.version> <lombok.version>1.18.16</lombok.version> <!-- ... --> </properties> <dependencies> <!-- ... --> <dependency> <groupId>org.springframework.data</groupId> <artifactId>spring-data-mongodb</artifactId> <version>2.1.6.RELEASE</version> </dependency> <dependency> <groupId>com.querydsl</groupId> <artifactId>querydsl-mongodb</artifactId> <version>${querydsl.version}</version> </dependency> <!-- ... --> </dependencies> <build> <!-- ... --> <plugins> <plugin> <groupId>com.mysema.maven</groupId> <artifactId>apt-maven-plugin</artifactId> <version>1.1.3</version> <executions> <execution> <goals> <goal>process</goal> </goals> <configuration> <outputDirectory>target/generated-sources/java</outputDirectory> <processor> org.springframework.data.mongodb.repository.support.MongoAnnotationProcessor </processor> </configuration> </execution> </executions> </plugin> <!-- ... --> </plugins> </build>
解决方案
1. 调整@QueryInit注解的初始化深度
原注解@QueryInit("*.*")仅能初始化两层嵌套属性,需要明确指定三层初始化:
// 在SpeedViolation类的fact1字段上修改 @NotNull @QueryEmbedded @QueryInit("*.*.*") protected Fact fact1;
或者在中间层Fact类的car字段上添加注解,显式初始化下一层:
// 在Fact类的car字段上添加 @QueryEmbedded @QueryInit("*") private Car car;
2. 升级依赖版本以兼容JDK11
原项目使用的Spring Boot 2.1.6和Querydsl 4.2.2对JDK11的兼容性较差,建议升级到更稳定的版本:
- 将Spring Boot版本升级至2.7.x及以上(该版本全面支持JDK11)
- 同步升级Querydsl至5.x系列,确保与Spring Data MongoDB版本匹配
- 升级spring-data-mongodb到对应Spring Boot管理的版本,避免版本冲突
3. 替换旧的APT注解处理器
原项目使用的com.mysema.maven:apt-maven-plugin是旧版插件,JDK11的注解处理机制已发生变化,建议改用maven-compiler-plugin内置的注解处理:
- 移除
apt-maven-plugin配置 - 在
maven-compiler-plugin的annotationProcessorPaths中添加Querydsl的Mongo处理器:
<plugin> <groupId>org.apache.maven.plugins</groupId> <artifactId>maven-compiler-plugin</artifactId> <version>${maven-compiler-plugin.version}</version> <configuration> <source>${java.version}</source> <target>${java.version}</target> <annotationProcessorPaths> <!-- 原有注解处理器 --> <path> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-configuration-processor</artifactId> <version>${spring-boot.version}</version> </path> <path> <groupId>org.projectlombok</groupId> <artifactId>lombok</artifactId> <version>${lombok.version}</version> </path> <!-- 添加Querydsl MongoDB处理器 --> <path> <groupId>com.querydsl</groupId> <artifactId>querydsl-apt</artifactId> <version>${querydsl.version}</version> <classifier>mongodb</classifier> </path> <!-- ...其他处理器 --> </annotationProcessorPaths> </configuration> </plugin>
内容的提问来源于stack exchange,提问作者Шатов Данил
相关产品推荐
相关产品推荐

