有没有办法执行单查询联接获取"with the same entity twice"?



我有一些像:

@Entity
public class Edge {
@ManyToOne(fetch = FetchType.EAGER)
@Fetch(value = FetchMode.JOIN)
@JoinColumn(name = "start_node", referencedColumnName = "id")
Node start;

@ManyToOne(fetch = FetchType.EAGER)
@Fetch(value = FetchMode.JOIN)
@JoinColumn(name = "end_node", referencedColumnName = "id")
Node end;
}

调用JPA连接器提供的findAll()方法,我想获得以下形式的(单个)查询:

SELECT * FROM EDGE edge, NODE start, NODE end WHERE edge.start_id = start.id AND edge.end_id = end.id

相反,框架首先执行单个查询以获取所有边,然后对节点执行多个查询(理想情况下为边执行一个查询)。我是个冬眠乞讨者。我认为这是一个很常见的问题。我找到了很多关于这个问题的资料,但是没有找到正确的答案。

简而言之,JPA默认忽略HibernateFetchMode.JOIN。它这样做的原因是JPA获取实体懒惰(只有当你需要它,例如,当你调用getStart())。因此,应用程序只在需要时才将资源保留给。.

即时抓取通常是一个糟糕的选择,应该避免,除非你真的需要。我建议阅读这个帖子,因为它列出了许多与此相关的阅读材料。

可以做的是使用@NamedEntityGraph来定义实体的急切获取。在这里,您指定需要急切获取的属性(startend)。要了解更多信息,请参见这里和这里。

@Entity
@Table(name = "edge")
@NamedEntityGraph(name = "Edge.nodes", attributeNodes = {
@NamedAttributeNode("start"),
@NamedAttributeNode("end")
}) // This is the important annotation
public class Edge {
@EmbeddedId
private EdgeKey id = new EdgeKey();
private int value;
@ManyToOne
@MapsId("startId")
@JoinColumn(name = "start_id", referencedColumnName = "id")
private Node start;
@ManyToOne
@MapsId("endId")
@JoinColumn(name = "end_id", referencedColumnName = "id")
private Node end;
// getters, setters...
}
@Embeddable
public class EdgeKey implements Serializable {
@Column(name = "start_id", nullable = false)
Integer startId;
@Column(name = "end_id", nullable = false)
Integer endId;
// getters, setters, equals and hash code...
}

此外,您用@EntityGraph:

注释JPA存储库方法
@Repository
public interface EdgeRepository extends JpaRepository<Edge, Integer> {
@Override
@EntityGraph(value = "Edge.nodes", type = EntityGraph.EntityGraphType.LOAD)
List<Edge> findAll(); // You override the default implementation of findAll()
@EntityGraph(value = "Edge.nodes", type = EntityGraph.EntityGraphType.LOAD)
Edge getByValue(int value); // other example
}

这将导致一个类似于下面的查询:

SELECT edge0_.end_id AS end_id1_0_0_,
edge0_.start_id AS start_id2_0_0_,
node1_.id AS id1_1_1_,
node2_.id AS id1_1_2_,
edge0_.value AS value3_0_0_,
node1_.value AS value2_1_1_,
node2_.value AS value2_1_2_
FROM edge edge0_
LEFT OUTER JOIN node node1_ ON edge0_.start_id=node1_.id
LEFT OUTER JOIN node node2_ ON edge0_.end_id=node2_.id

相关内容

最新更新