Объединение критериев JPA 2 с абстрактной коллекцией

#java #hibernate #jpa #jpa-2.0 #criteria

#java #переход в спящий режим #jpa #jpa-2.0 #критерии

Вопрос:

Есть ли какой-либо способ объединить класс Player с менеджером в иерархии, как показано ниже, используя Criteria API? Я хотел бы найти всех игроков с менеджером данного идентификатора в моем DAO и попробовал что-то вроде этого:

Запрос:

 CriteriaBuilder cb = em.getCriteriaBuilder();
CriteriaQuery<Player> query = cb.createQuery(Player.class);
Root<Player> root = query.from(Player.class);

Join<Player, PlayerTeam> playerTeamJoin = root.join(Player_.playerTeam);
Join<PlayerTeam, PlayerTeamAssignment> playerTeamAssignmentJoin = playerTeamJoin.join(PlayerTeam_.playerTeamAssignments);

// Desired statement:
Predicate predicate = cb.equal(playerTeamAssignmentJoin.get(ManagerAssignment_.manager), manager);
  

Иерархия классов:

 @Entity
class Player {
  @OneToOne(mappedBy = "player")
  PlayerTeam playerTeam;
}

@Entity
class PlayerTeam {
  @JoinColumn(name = "PLAYER_ID", referencedColumnName = "ID")
  Player player;
  @OneToMany(mappedBy = "playerTeam")
  Collection<PlayerTeamAssignment> playerTeamAssignments;
}

@Entity
@DiscriminatorColumn(name = "ASSIGNMENT_TYPE", discriminatorType = DiscriminatorType.STRING)
public abstract class PlayerTeamAssignment {  // It has three implementations
  @ManyToOne
  @JoinColumn(name = "PLAYER_TEAM_ID", referencedColumnName = "ID")
  PlayerTeam playerTeam;
} 

@Entity
@DiscriminatorValue("INDIVIDUAL")
public class ManagerAssignment extends PlayerTeamAssignment {
  @ManyToOne
  @JoinColumn(name = "MANAGER_ID", referencedColumnName = "ID")
  Manager manager; // id inside
}
  

Комментарии:

1. Я думаю, что ваша модель данных может нуждаться в некоторой переработке.

2. Спасибо за ответ. Дело в том, что его нельзя изменить.. Имена классов упрощены для целей вопроса — на самом деле они представляют собой немного более сложную структуру

3. Обратите внимание, что PlayerTeamAssignment у него нет поля manager . Почему бы не начать свой запрос с ManagerAssignment , т.е. SELECT ... FROM ManagerAssignment JOIN ... ?

4. В качестве альтернативы вы можете либо включить type() объект объекта в свое предложение where, либо, в JPA 2.1, предоставить поставщику treat() объект в качестве подкласса.

5. Еще раз спасибо за ваши ответы! Я попробую с вашими предложениями

Ответ №1:

Я уже нашел решение своей проблемы. Мне пришлось использовать Path

 Join<Player, PlayerTeam> playerTeamJoin = root.join(Player_.playerTeam);
Join<PlayerTeam, PlayerTeamAssignment> playerTeamAssignments = root.join(PlayerTeam_.playerTeamAssignments);
Path managerPath = ((Path) playerTeamAssignments.as(ManagerAssignment.class)).get(ManagerAssignment_.manager));
  

и вы можете использовать его, например, в предикате:

  Predicate predicate = cb.equal(managerPath.get(Manager_.globalId), managerId);
  

Комментарии:

1. Я получаю сообщение об ошибке не удается привести функцию приведения к Path