为何Spring Data JPA的findByEntityId查询会执行关联操作?
为什么Spring Data JPA的
findByBarId会生成关联查询而非直接查询外键字段? 实体类定义
Foo 类
@Entity public class Foo { @Id (...) private Long id; @OneToOne(...) private Bar bar; // and other fields }
Bar 类
@Entity public class Bar { @Id(...) private Long id; // and other fields }
问题现象
当在FooRepository中定义findByBarId(Long barId)方法时,Spring Data JPA生成的SQL为:
select ... from foo left outer join bar where foo.id = bar.id where bar.id = ?
而预期生成的SQL是直接查询Foo表的外键字段:
select ... from foo where foo.bar_id = ?
已知改用findByBar(Bar bar)可以生成预期的SQL,下面解释原因:
原因解析
方法名的属性路径解析逻辑
Spring Data JPA是按照属性路径来解析方法名的。findByBarId会被拆解为:先访问Foo类的bar属性(关联的Bar实体),然后再访问Bar实体的id属性。框架会认为你需要基于关联实体Bar的id进行筛选,因此会生成关联JOIN语句,通过关联后的Bar表id字段来过滤数据。外键字段与关联属性的区别
Foo表中实际存储的bar_id是外键字段,但在实体类中你只定义了关联属性bar,并没有直接映射这个外键字段。框架不会自动将Bar.id的查询逻辑映射到Foo的外键字段上,而是严格按照你定义的实体属性路径来构建查询。findByBar(Bar bar)的逻辑
当传入的参数是Bar实体对象时,Spring Data JPA会直接识别出:只需要比对Foo表中的bar_id外键与传入Bar实体的id即可,不需要关联查询Bar表,因此会生成直接查询外键的SQL。
如果想直接通过外键字段查询,也可以改用findByBar_Id(Long barId)(注意下划线分隔),或者在Foo类中直接映射barId外键字段并添加对应的Getter方法。
内容的提问来源于stack exchange,提问作者chl
相关产品推荐
相关产品推荐

