Как инициализировать ЛЕНИВУЮ сущность на несколько слоев глубже в JPA?

#hibernate #jpa #lazy-loading

#спящий режим #jpa #отложенная загрузка

Вопрос:

У меня есть глубокие отношения на нескольких уровнях:

 class Person {
  @Id
  @Column(name = "PERSON_ID")
  private Long personId;

  @OneToMany(fetch = FetchType.EAGER, mappedBy = "person")
  private Set<Parameter> parameters;

  [... various other attributes omitted]
} 

class Parameter {
  @Id
  @Column(name = "PARAMETER_ID")
  private Long personId;

  @ManyToOne(cascade = CascadeType.ALL)
  @JoinColumn(name = "GAME_ID", nullable = false)
  private Game game;

  @ManyToOne(fetch = FetchType.LAZY)
  @JoinColumn(name = "PERSON_ID")
  @JsonIgnore
  private Person person;

  [... various other attributes omitted]
} 

class Game {
  @Id
  @Column(name = "GAME_ID")
  private Long gameId;

  @OneToMany(fetch = FetchType.LAZY, mappedBy = "game") // this is the attribute, that sometimes is required sometimes is not
  private Set<GameRule> gameRules;

  @OneToMany(fetch = FetchType.LAZY, mappedBy = "game")
  @JsonIgnore
  private Set<Parameter> parameters;

  [... various other attributes omitted]
}

class GameRule {
  @Id
  @Column(name = "GAME_RULE_ID")
  private Long gameRuleId;

  @ManyToOne(fetch = FetchType.LAZY)
  @JoinColumn(name="GAME_ID", nullable = false)
  @JsonIgnore
  private Game game;

  [... various other attributes omitted]
}
  

Может кто-нибудь сказать мне, как я могу «присоединиться к выборке» game.gameRules при запросе person ?
Я пытался создать @NamedEntityGraph on game gameRules атрибутом)
и использовать его в person репозитории findAll с @EntityGraph , но использование
entitygraph в person репозитории вызвало исключение, в котором Hibernate не смог найти gameRules атрибут person (неудивительно).

Итак, как кто-то может инициализировать ленивую сущность на уровне члена на несколько уровней глубже? Спасибо,

Ответ №1:

Поскольку ваши отношения в этом случае являются вложенными, вам нужно использовать subgraph и @namedsubg graph, как показано ниже.

используйте graph.person.parameters в качестве имени графика в вашем методе репозитория.

 @NamedEntityGraph(name = "graph.person.parameters", attributeNodes = {
        @NamedAttributeNode(value = "parameters", subgraph = "parameters.game") }, subgraphs = {
                @NamedSubgraph(name = "parameters.game", attributeNodes = {
                        @NamedAttributeNode(value = "game", subgraph = "game.gameRules") }),
                @NamedSubgraph(name = "GameRule ", attributeNodes = {
                        @NamedAttributeNode(value = "GameRule ") }) })