Spring Data - готовый выбор на @OneToOne - PullRequest
0 голосов
/ 19 февраля 2020

У меня есть две сущности:

@Entity
@Table(name = "Something")
public class SomethingEntity implements Serializable {
    @Id
    @GeneratedValue(strategy = GenerationType.SEQUENCE, generator = "SOMETHING_SEQ")
    @SequenceGenerator(sequenceName = "SOMETHING_SEQ", allocationSize = 1, name = "SOMETHING_SEQ")
    @Column(name = "SOMETHING_ID", precision = 18, scale = 0, nullable = false)
    private Long somethingId;

    @Column(name = "SIMPLE_FIELD", length = 3, nullable = true)
    private String simpleField;

    @OneToOne(cascade = CascadeType.ALL, mappedBy = "somethingId")
    private OtherEntity other;
}

@Entity
@Table(name = "OTHER")
public class OtherEntity implements Serializable {
    @Id
    @OneToOne
    @JoinColumn(name = "SOMETHING_ID")
    private SomethingEntity somethingId;

    @Column(name = "OTHER_SIMPLE_FIELD", precision = 18, scale = 2, nullable = false)
    private Double otherSimpleField;
}

Я хочу, чтобы Spring-Data с нетерпением получал otherEntity. Я знаю, что он не работает по умолчанию, поэтому мой метод хранилища:

@EntityGraph(attributePaths = {"other"})
List<SomethingEntity> findAll(Predicate predicate);

Это не работает, и я думаю, это из-за @OneToOne. Я также попробовал JOIN FETCH, просто выберите simpleField (предикат в моем примере - QueryDSL), ничего не работает.

Самое удивительное, что начальный SQL на самом деле правильный - он содержит правильные объединения и выбирает правильные поля. Затем Spring-Data в любом случае загружает каждое отношение @OneToOne по id, вызывая 100 запросов вместо 1.

1 Ответ

0 голосов
/ 20 февраля 2020

Я не понимаю, как вы используете @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);

Другой вариант - создать метод CriteriaQuery в репозитории yout следующим образом:

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();
...