问题描述
我实际上是在尝试使用JPA @OneToOne
注释将Child
实体链接到其Parent
.
I'm actually trying to use JPA @OneToOne
annotation to link a Child
entity to its Parent
.
工作正常,除了以下事实:在获取Child
列表时,JPA引擎(在这种情况下为Hibernate)进行1 + n次查询.
It's working well, except the fact that when getting a list of Child
s, the JPA engine (Hibernate in this case) make 1+n queries.
这是Hibernate查询的日志:
Here is the log of the Hibernate queries :
select child0_.id as id1_0_, child0_.parent as parent3_0_, child0_.value as value2_0_ from child child0_
select parent0_.id as id1_1_0_, parent0_.something as somethin2_1_0_ from parent parent0_ where parent0_.id=?
select parent0_.id as id1_1_0_, parent0_.something as somethin2_1_0_ from parent parent0_ where parent0_.id=?
select parent0_.id as id1_1_0_, parent0_.something as somethin2_1_0_ from parent parent0_ where parent0_.id=?
使用完全相同的实体定义,尤其是当我得到一个孩子时,JPA使用预期的JOIN执行查询:
Using exactly the same entities definition, when I get a child in particular, JPA executes the query with expected JOIN :
select child0_.id as id1_0_0_, child0_.parent as parent3_0_0_, child0_.value as value2_0_0_, parent1_.id as id1_1_1_, parent1_.something as somethin2_1_1_ from child child0_ left outer join parent parent1_ on child0_.parent=parent1_.id where child0_.id=?
这是Child
实体定义:
@Data
@NoArgsConstructor
@AllArgsConstructor
@Builder
@Entity
@Table(name = "child")
public class Child {
@Id
private Long id;
@Column
private String value;
@OneToOne(optional = false)
@JoinColumn(name = "parent")
private Parent parent;
}
和Parent
实体:
@Data
@NoArgsConstructor
@AllArgsConstructor
@Builder
@Entity
@Table(name = "parent")
public class Parent {
@Id
private Long id;
@Column
private String something;
}
您可以在此处找到运行代码的完整示例: https://github.com/Alexandre-Carbenay/demo-jpa-onetoone
You can find a complete example of running code here :https://github.com/Alexandre-Carbenay/demo-jpa-onetoone
在使用Parent
获取Child
实体列表时,有没有一种方法可以避免1 + n个查询?
Is there a way to avoid the 1+n queries when getting the list of Child
entities with Parent
?
推荐答案
我终于找到了一个比JOIN FETCH
更好的解决方案,该解决方案也适用于QueryDsl,并在存储库方法上使用了@EntityGraph
批注.
I finally found a better solution than JOIN FETCH
that also works with QueryDsl, using @EntityGraph
annotation on repository methods.
这是更新的Child
定义:
@Data
@NoArgsConstructor
@AllArgsConstructor
@Builder
@Entity
@NamedEntityGraph(name = "Child.withParent", attributeNodes = @NamedAttributeNode("parent"))
@Table(name = "child")
public class Child {
@Id
private Long id;
@Column
private String value;
@OneToOne(optional = false)
@JoinColumn(name = "parent")
private Parent parent;
}
和ChildJpaRepository
定义:
public interface ChildJpaRepository extends JpaRepository<Child, Long>, QueryDslPredicateExecutor<Child> {
@Override
@EntityGraph("Child.withParent")
List<Child> findAll();
@Override
@EntityGraph("Child.withParent")
List<Child> findAll(Predicate predicate);
}
感谢Simon Martinelli和Vlad Mihalcea的帮助
Thanks to Simon Martinelli and Vlad Mihalcea for your help
这篇关于JPA @OneToOne选择具有N + 1个查询的列表的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持!