Как мы можем представить в Hibernate (HBM) ленивое отношение многие-к-одному, позволяя ссылаться на тот же класс в активном режиме? - PullRequest
0 голосов
/ 17 октября 2019

Я пытаюсь сделать некоторые из моих отношений «многие к одному» в моих спящих файлах HBM ленивыми. Конкретно у меня есть класс DataElement , который ссылается на элемент Filter в отношении многие к одному, я хочу сделать его ленивым, сохраняя доступ к Filter eagerв других частях приложения.

Я попытался изменить мои файлы HBM и обнаружил, что lazy = "true" доступно только на уровне класса

DataElement 's mapping ( Я хочу, чтобы множественные к одному с фильтром были ленивыми )

<hibernate-mapping package="project.me" default-lazy="false" auto-import="false">
  <class name="DataElement" table="DATA_ELEMENT">
    <id name="id" type="java.lang.Long" column="ID"/>
    <many-to-one name="filter" class="project.me.Filter" column="FILTER_ID" cascade="all"/>
  </class>
</hibernate-mapping>

FilterAudit mapping ( Я хочу, чтобы многиек одному с фильтром, к которому нужно стремиться )

<hibernate-mapping package="project.me" default-lazy="false" auto-import="false">
  <class name="FilterAudit" table="FILTER_AUDIT">
    <id name="id" type="java.lang.Long" column="ID"/>
    <many-to-one name="filter" class="project.me.Filter" column="FILTER_ID" cascade="all"/>
  </class>
</hibernate-mapping>

Фильтр mapping

<hibernate-mapping package="project.me" default-lazy="false" auto-import="false">
    <class name="Filter" table="FILTERS" lazy="true">
        <id name="id" type="java.lang.Long" column="M_ID"/>
        <property name="type" type="filterType" column="M_FILTER_TYPE"/>
        <many-to-one name="predicate" class="Predicate" column="PRED_ID" unique="true" not-null="true" cascade="all"/>
    </class>
</hibernate-mapping>

Путем установки lazy = "true" в Фильтр уровень класса, я загружаю все DTO в приложении Фильтр лениво, и я не хочу этого

Есть ли способ указать ленивую загрузку только для отношение между DataElement и Filter при сохранении нагрузки между FilterAudit и Filter рвется?

1 Ответ

0 голосов
/ 18 октября 2019

Моя рекомендация: не используйте нетерпеливое извлечение. Это приводит к несогласованности и иногда странным запросам. Кроме того, трудно оптимизировать производительность, когда вы используете нетерпеливую выборку. В упомянутом случае я бы создал разные методы для вызова базы данных с некоторыми выборочными соединениями или графами сущностей.

Я не использую HBM (или другое отображение на основе XML). Я использую аннотации, почему не могу предоставить вам ответ с отображением XML ( HBM, похоже, в любом случае устарел ).

Мой предпочтительный способ - использовать API критериев JPA вместо JPQL. Некоторые люди говорят, что JPQL более понятен, но я предпочитаю API-интерфейс Criteria-safe, который менее подвержен ошибкам. Я предпочитаю графы сущностей, потому что их проще использовать динамически, чем выборочные объединения. Тем не менее, другие опции также работают.

Сначала я бы настроил классы сущностей, соответствующие Статья Влада Михальчи . (Я делаю вывод о однонаправленных отношениях.)

@Entity
@Table(name = "DATA_ELEMENT")
public class DataElement {

    @Id
    @GeneratedValue
    @Column(name = "ID")
    private Long id;

    @ManyToOne(fetch = FetchType.LAZY)
    @JoinColumn(name = "FILTER_ID")
    private Filter filter;

    //Constructors, getters and setters...

    @Override
    public boolean equals(Object o) {
        if (this == o) return true;
        if (!(o instanceof DataElement )) return false;
        return id != null && id.equals(((DataElement) o).getId());
    }

    @Override
    public int hashCode() {
        return 56;
    }
}

Аналогично для FilterAudit (также FetchType.LAZY) ...

И затем Filter (не так интересно, потому что это однонаправленный).

@Entity
@Table(name = "FILTERS")
public class Filter {

    @Id
    @GeneratedValue
    @Column(name = "M_ID")
    private Long id;

    // Other attributes omitted...

    //Constructors, getters and setters...

    @Override
    public boolean equals(Object o) {
        if (this == o) return true;
        if (!(o instanceof Filter )) return false;
        return id != null && id.equals(((Filter) o).getId());
    }

    @Override
    public int hashCode() {
        return 14;
    }
}

Теперь соответствующая часть для инициализации отложенных нагрузок (или нет) реализуется в этом случае с помощью API-критериев JPA и графиков сущностей.

public DataElement findByIdWithFilter(long id) {

    EntityGraph<DatElement> graph = entityManager.createEntityGraph(DataElement.class);
    graph.addAttributeNodes("filter");

    CriteriaBuilder cb = entityManager.getCriteriaBuilder();
    CriteriaQuery<DatElement> cq = cb.createQuery(DatElement.class);
    Root<DatElement> root = cq.from(DatElement.class);

    cq.where(cb.equal(root.get("id"), id));

    TypedQuery<DatElement> typedQuery = entityManager.createQuery(cq);
    typedQuery.setHint("javax.persistence.fetchgraph", graph);

    DatElement response = null;
    try {
        response = typedQuery.getSingleResult();
    }
    catch(NoResultException nre) {}

    return response;
}

Для извлеченияобъект того же класса без его связи, просто опустите граф сущности.

public DataElement findByIdWithoutFilter(long id) {

    CriteriaBuilder cb = entityManager.getCriteriaBuilder();
    CriteriaQuery<DatElement> cq = cb.createQuery(DatElement.class);
    Root<DatElement> root = cq.from(DatElement.class);

    cq.where(cb.equal(root.get("id"), id));

    return entityManager.createQuery(cq).getSingleResult();
}
...