Критерии гибернации с самостоятельным присоединением

На прошлой неделе я изучал Hibernate, Spring и JPA и застрял при попытке создать критерии для следующего сценария:

Допустим, у меня есть 2 таблицы:

Игра

  • Я бы

PlayedGame

  • Я бы
  • account_ref -> ссылка на некоторую таблицу счетов
  • game_id -> ссылка на игру

Сопоставление объектов:

Game {

 @id
 Long id;

 @OneToMany(mappedBy = "game")
 Set<Player> players;

}

PlayedGame {

 @id
 Long id;

 Long account_ref;

 @ManyToOne
 @JoinColumn(name = "game_id", referencedColumnName = "id")
 Game game;
}

Теперь я хочу запросить следующий сценарий: - Я хочу найти все игры, в которые играл конкретный игрок (P), где игрок (A) был его частью. Более конкретно, что два человека, принадлежащие к одной и той же игре

В SQL это может быть сделано с помощью чего-то вроде (что запрос должен быть):

SELECT DISTINCT p1.* FROM Player as p1 
INNER JOIN Player as p2 ON p1.game_id=p2.game_id 
WHERE p1.account_ref=P AND p2.account_ref=A 

Можно ли сделать это аккуратно с помощью Criteria в Hibernate?

1 ответ

Решение

Возможно, это возможно с Criteria API Hibernate, но не прямо.

В простом случае потребуется дважды объединить один и тот же путь ассоциации (один для A и один для P):

Criteria gameCriteria = ((HibernateEntityManager) em).getSession().createCriteria(Game.class);

Criteria playedGamesOfACriteria = gameCriteria.createCriteria("playedGames", "pga");
Criteria accountOfACriteria = playedGamesOfACriteria.createCriteria("account", "a");
accountOfACriteria.add(Restrictions.idEq(a.id));

Criteria playedGamesOfPCriteria = gameCriteria.createCriteria("playedGames", "pgp");
Criteria accountOfPCriteria = playedGamesOfPCriteria.createCriteria("account", "p");
accountOfPCriteria.add(Restrictions.idEq(p.id));

return gameCriteria.list();

Это не сработает из-за HHH-879.

Но вы можете использовать запрос JPA:

Query q = em.createQuery(
        "select g "
        + "from Game g "
        + "join g.playedGames pga "
        + "join pga.account a "
        + "join g.playedGames pgp "
        + "join pgp.account p "
        + "where a = ?1 and p = ?2"
);
q.setParameter(1, a);
q.setParameter(2, p);
return q.getResultList();

Это еще меньше кода.

Кроме того: Некоторые считают, что API Criteria устарел.

Другие вопросы по тегам