Hibernate @NotFound无匹配记录时关联查询结果异常求助
问题解决:Hibernate加载关联集合时的间歇性空值问题
依赖配置
<properties> <maven.compiler.source>11</maven.compiler.source> <maven.compiler.target>11</maven.compiler.target> <spring.version>5.3.29</spring.version> <hibernate.version>5.3.20.Final</hibernate.version> <oracle.version>19.3.0.0</oracle.version> </properties> <dependencies> <dependency> <groupId>org.springframework</groupId> <artifactId>spring-orm</artifactId> <version>${spring.version}</version> </dependency> <dependency> <groupId>org.springframework</groupId> <artifactId>spring-context</artifactId> <version>${spring.version}</version> </dependency> <dependency> <groupId>org.springframework</groupId> <artifactId>spring-test</artifactId> <version>${spring.version}</version> <scope>test</scope> </dependency> <dependency> <groupId>org.hibernate</groupId> <artifactId>hibernate-core</artifactId> <version>${hibernate.version}</version> </dependency> <!-- JDBC driver --> <dependency> <groupId>com.oracle.ojdbc</groupId> <artifactId>ojdbc10</artifactId> <version>${oracle.version}</version> <exclusions> <exclusion> <groupId>com.oracle.ojdbc</groupId> <artifactId>ucp</artifactId> </exclusion> </exclusions> </dependency> </dependencies>
实体关联关系
三个实体通过col_2关联,数据库无关联约束:
@Table(name = "test_a") @Entity public class A implements Serializable { @Id @Column(name = "col_1") private String col1; @Column(name = "col_2") private String col2; @OneToOne @JoinColumn(name = "col_2", referencedColumnName = "col_2",insertable = false,updatable = false) @NotFound(action = NotFoundAction.IGNORE) private B b; @OneToMany @JoinColumn(name = "col_2", referencedColumnName = "col_2", insertable = false, updatable = false) private List<C> cs; } @Table(name = "test_b") @Entity public class B implements Serializable { @Id @Column(name = "col_1") private String col1; @Column(name = "col_2") private String col2; } @Table(name = "test_c") @Entity public class C implements Serializable { @Id @Column(name = "col_1") private String col1; @Column(name = "col_2") private String col2; }
问题现象
加载A实体时,当关联的B实体无匹配记录,A的cs集合间歇性为空。异常场景下,系统会多次查询test_b表,最终查询test_c时绑定null作为参数。
问题原因
这是Hibernate 5.x版本中,处理@NotFound(action = NotFoundAction.IGNORE)与延迟加载集合时的已知行为:
当Hibernate加载A的延迟集合cs时,会尝试复用之前查询B关联的上下文。如果B不存在,@NotFound(IGNORE)会将B设为null,此时Hibernate错误地将null作为col_2的参数传递给cs的查询,而非使用A自身的col2值。这种间歇性源于Hibernate缓存和查询计划的不确定性。
解决方案
方案1:显式指定集合查询的Fetch模式
修改A实体中cs字段的注解,添加@Fetch(FetchMode.SELECT),强制Hibernate在查询集合时直接使用A实体的col2值,而非复用关联查询的上下文:
@OneToMany @JoinColumn(name = "col_2", referencedColumnName = "col_2", insertable = false, updatable = false) @Fetch(FetchMode.SELECT) private List<C> cs;
方案2:使用JPQL显式控制加载逻辑
在查询A实体时,通过JPQL显式指定加载cs集合,确保参数从A的col2获取:
SELECT a FROM A a LEFT JOIN FETCH a.cs WHERE a.col1 = :col1
关于双向关联生效的原因
配置双向关联后,Hibernate会明确从A实体的col2属性获取关联参数,而非依赖B关联查询的结果,因此避免了B不存在时的null值传递问题。
内容的提问来源于stack exchange,提问作者angrylittlebird
相关产品推荐
相关产品推荐

