JPA загружает сущности, но в списке @OneToMany только специфичные для загрузки - PullRequest
1 голос
/ 11 октября 2019

Ситуация: (с использованием сервера Payara)

У меня есть несколько Group с, и каждый Group имеет свой собственный определенный набор GroupMeeting с.

Эти GroupMeeting отслеживаются в течение нескольких лет. Каждый Group содержит 100-10000 GroupMeeting с. Но обычно запрашиваются и используются только текущие значения GroupMeeting текущего года.

Проблема:

Как загрузить все Group с, но загрузить только каждый Group s GroupMeeting Список для определенного интервала, например, только GroupMeeting s из 2019? Или, если необходимо, конкретные годы или диапазоны, например, 2017-2021 и т. Д.

Если я просто запускаю «SELECT *», то с FetchType.LAZY я получу пустое значение emtpy List<GroupMeeting>, нокак только я получу доступ к нему где-нибудь в коде, все элементы будут загружены.

Вопрос: Какова лучшая стратегия, т.е. несколько эффективная, но не слишком запутанная?

  • Есть ли простой запрос SQL / JPQL, который я могу выполнить с классами ниже?
  • Необходимы ли какие-то структурные изменения - особенно в аннотациях?
  • Должен ли я учитывать критерииAPI?
  • Нужно ли использовать два List<GroupMeeting>, один для часто используемых собраний, другой для «старых» собраний?

Пример: Вот два класса:

import java.util.ArrayList;
import java.util.List;
import javax.persistence.CascadeType;
import javax.persistence.Entity;
import javax.persistence.FetchType;
import javax.persistence.GeneratedValue;
import javax.persistence.Id;
import javax.persistence.JoinTable;
import javax.persistence.OneToMany;

@Entity
public class Group {
    @Id //
    @GeneratedValue() //
    private long id;

    private String name;

    @OneToMany(cascade = CascadeType.ALL, fetch = FetchType.LAZY, orphanRemoval = true) @JoinTable(name = "group_meetings") //
    private final List<GroupMeeting> meetings = new ArrayList<>();
}

и

import java.util.Date;
import javax.persistence.Entity;
import javax.persistence.GeneratedValue;
import javax.persistence.Id;

@Entity
public class GroupMeeting {
    @Id //
    @GeneratedValue() //
    private long id;

    private String  title;
    private Date    start;
    private Date    end;
}

1 Ответ

1 голос
/ 12 октября 2019

Вы можете использовать фильтры Hibernate для достижения этой цели, например:

@Entity
@FilterDef(name="groupMeetingFilter",
        parameters={@ParamDef( name="fromDate", type="date"), @ParamDef(name="toDate", type="date")} )
public class Group {
    @Id //
    @GeneratedValue() //
    private long id;

    private String name;

    @OneToMany(cascade = CascadeType.ALL, fetch = FetchType.LAZY, orphanRemoval = true) @JoinTable(name = "group_meetings")
    @Filter(
        name = "groupMeetingFilter",
        condition="start <= :fromDate and end >= :toDate"
    )
    private final List<GroupMeeting> meetings = new ArrayList<>();
}

И вам нужно включить свой фильтр где-то в вашем приложении, например так:

Session session = HibernateUtil.getSessionFactory().openSession();
Filter filter = session.enableFilter("groupMeetingFilter");
//Define here the dates that you want
filter.setParameter("fromDate", new Date());
filter.setParameter("toDate", new Date());

Выможет пойти дальше с вашими исследованиями и сделать глобальный фильтр доступным, например, если вы используете Spring.

...