Hibernate Spring数据-在@OneToOne上进行即时获取

Hibernate Spring数据-在@OneToOne上进行即时获取,hibernate,jpa,spring-data-jpa,spring-data,Hibernate,Jpa,Spring Data Jpa,Spring Data,我有两个实体: @实体 @Tablename=某物 公共类SomethingEntity实现可序列化{ @身份证 @GeneratedValuestrategy=GenerationType.SEQUENCE,generator=SOMETHING_SEQ @SequenceGeneratorsequenceName=SOMETHING,allocationSize=1,name=SOMETHING @Columnname=SOMETHING\u ID,精度=18,比例=0,可空=false 私

我有两个实体:

@实体 @Tablename=某物 公共类SomethingEntity实现可序列化{ @身份证 @GeneratedValuestrategy=GenerationType.SEQUENCE,generator=SOMETHING_SEQ @SequenceGeneratorsequenceName=SOMETHING,allocationSize=1,name=SOMETHING @Columnname=SOMETHING\u ID,精度=18,比例=0,可空=false 私人长某物; @Columnname=SIMPLE_字段,长度=3,可空=true 私有字符串simpleField; @OneToOnecascade=CascadeType.ALL,mappedBy=somethingId 私人或其他实体; } @实体 @Tablename=OTHER 公共类OtherEntity实现可序列化{ @身份证 @奥内托内 @JoinColumnname=SOMETHING\u ID 私人某物实体某物ID; @Columnname=OTHER\u SIMPLE\u字段,精度=18,比例=2,可空=false 私人双基地; } 我希望Spring数据能够获取其他实体。我知道默认情况下它不起作用,所以我的存储库方法是:

@EntityGraph(attributePaths = {"other"})
List<SomethingEntity> findAll(Predicate predicate);
它不起作用,我猜是因为@OneToOne。我还尝试了连接获取,在我的示例中,simpleField谓词的简单选择是QueryDSL,没有任何效果


最令人惊讶的是,初始SQL实际上是正确的——它包含正确的连接并选择正确的字段。然后Spring数据按id加载每个@OneToOne关系,导致100个查询而不是1个查询。

我不理解您对@EntityGraph的使用,请尝试在实体中使用它,如下所示:

@NamedEntityGraphs({
    @NamedEntityGraph(name = "graph.SomethingEntity.OtherEntity", attributeNodes = @NamedAttributeNode("other"))
})
public class SomethingEntity implements Serializable {
[...]
EntityGraph graph = this.em.getEntityGraph("graph.SomethingEntity.OtherEntity");
Map hints = new HashMap();
hints.put("javax.persistence.fetchgraph", graph);//Important fetchgraph no other type
return entityManager.find(SomethingEntity.class,ID_OF_SOMETHING_ENTITY,  hints);
CriteriaBuilder cb = entityManager.getCriteriaBuilder();
CriteriaQuery<SomethingEntity> cq = cb.createQuery(SomethingEntity.class);

//Need to define variable root to apply fetch
Root<SomethingEntity> rootSE = cq.from(SomethingEntity.class);

/* Use metamodel (in eclipse, property project / JPA / Canonical metamodel
 * and select src folder in source to allow autogenerated metamodels)
 */
rootSE.fetch(SomethingEntity_.other);

// Set your predicates
cq.where(cb.equals(rootSE.get(SomethingEntity_.somethingId),ID_OF_SOMETHING_ENTITY));

cq.select(rootSE);

entityManager.createQuery(cq).getSingleResult();
并在存储库方法中使用实体图,如下所示:

@NamedEntityGraphs({
    @NamedEntityGraph(name = "graph.SomethingEntity.OtherEntity", attributeNodes = @NamedAttributeNode("other"))
})
public class SomethingEntity implements Serializable {
[...]
EntityGraph graph = this.em.getEntityGraph("graph.SomethingEntity.OtherEntity");
Map hints = new HashMap();
hints.put("javax.persistence.fetchgraph", graph);//Important fetchgraph no other type
return entityManager.find(SomethingEntity.class,ID_OF_SOMETHING_ENTITY,  hints);
CriteriaBuilder cb = entityManager.getCriteriaBuilder();
CriteriaQuery<SomethingEntity> cq = cb.createQuery(SomethingEntity.class);

//Need to define variable root to apply fetch
Root<SomethingEntity> rootSE = cq.from(SomethingEntity.class);

/* Use metamodel (in eclipse, property project / JPA / Canonical metamodel
 * and select src folder in source to allow autogenerated metamodels)
 */
rootSE.fetch(SomethingEntity_.other);

// Set your predicates
cq.where(cb.equals(rootSE.get(SomethingEntity_.somethingId),ID_OF_SOMETHING_ENTITY));

cq.select(rootSE);

entityManager.createQuery(cq).getSingleResult();
另一个选项是在yout repository方法中创建CriteriaQuery,如下所示:

@NamedEntityGraphs({
    @NamedEntityGraph(name = "graph.SomethingEntity.OtherEntity", attributeNodes = @NamedAttributeNode("other"))
})
public class SomethingEntity implements Serializable {
[...]
EntityGraph graph = this.em.getEntityGraph("graph.SomethingEntity.OtherEntity");
Map hints = new HashMap();
hints.put("javax.persistence.fetchgraph", graph);//Important fetchgraph no other type
return entityManager.find(SomethingEntity.class,ID_OF_SOMETHING_ENTITY,  hints);
CriteriaBuilder cb = entityManager.getCriteriaBuilder();
CriteriaQuery<SomethingEntity> cq = cb.createQuery(SomethingEntity.class);

//Need to define variable root to apply fetch
Root<SomethingEntity> rootSE = cq.from(SomethingEntity.class);

/* Use metamodel (in eclipse, property project / JPA / Canonical metamodel
 * and select src folder in source to allow autogenerated metamodels)
 */
rootSE.fetch(SomethingEntity_.other);

// Set your predicates
cq.where(cb.equals(rootSE.get(SomethingEntity_.somethingId),ID_OF_SOMETHING_ENTITY));

cq.select(rootSE);

entityManager.createQuery(cq).getSingleResult();

我知道默认情况下它不起作用。Hibernate中的可选/可为空OneToOne始终是渴望的。是的,也许这是个问题。我自己加载这些关系,然后在不知道我加载了它们的情况下休眠,试图一个接一个地手动加载它们,可能是因为OneToOne很急切。我不希望一个接一个地抓取关系。如果它们被加载并在持久性上下文中,那么Hibernate不会再次加载它们。你的问题需要更多的上下文。你说我不想一个接一个地抓取关系是什么意思?这正是我所拥有的,在Spring数据中,你就是这样做的。你可能需要像这样的实体中的注释@JoinColumn:@OneToOnecascade=CascadeType.ALL,mappedBy=somethingId@JoinColumnname=somethin\u ID private OtherEntity other;