API критериев JPA и два соединения в одном выражении пути

Моя проблема очень похожа на этот старый вопрос: Критерии гибернации с самостоятельным присоединением, но я ' d требуется чистое решение JPA, не относящееся к Hibernate, для идентичной проблемы. В настоящее время я использую Hibernate 4.3 в качестве поставщика JPA, но при необходимости могу обновить его. У меня есть следующие сущности:

  • Игра, в которой может быть много записей Результат, по одной на каждого игрока, который в нее играл.
  • GameResult принадлежит Game и относится к игроку, который принимал участие. В нем нет обратной ссылки на игру, которая владеет
  • Игрок, сыгравший в игру.

Теперь я хочу создать запрос, который находит все игры, в которые я играл против определенного оппонента, и извлекает наши результаты. Я получил следующий запрос JPA:

String strQuery = "SELECT g, my_result, their_result FROM Game g JOIN g.results my_result JOIN  g.results their_result WHERE my_result.player=:p1 AND their_result.player=:p2";

Кажется, это работает, но я хотел бы преобразовать его в Criteria API, и я полный новичок, когда дело доходит до Criteria API. Для начала получил следующее:

Root<Game> game = query.from(Game.class);
Join<Game, GameResult> result_mine = game.join("results");

Пока все просто. Но теперь я не знаю, как подключить result_theirs к этой части. Я пробовал следующее:

Join<Game, GameResult> result_theirs = game.join("results");
result_mine.join( *what should I put here* , result_theirs);

//or:
Selection<Game> alias_game = game.alias("g");
Join result_theirs = result_mine.join(alias_game, "results"); //does not compile

//or:
Join result_theirs = result_mine.join(game.get("results")); //does not compile


//or:
Join<Game, GameResult> result_theirs = game.join("results");
result_mine.join(result_theirs); //does not compile

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

Итак, что я делаю не так и как я могу перевести вышеуказанный запрос JPA в код API критериев?


person Maciek    schedule 01.07.2017    source источник


Ответы (1)


Ваш третий или правильный, за исключением того, что вы присоединяетесь к нему дважды

Ваша строка result_mine.join(result_theirs); пытается присоединиться к GameResult к GameResult, что не может быть выполнено, поскольку в вашем сопоставлении сущностей указано только, как присоединиться Game к GameResult (но не GameResult к GameResult), первое уже сделано Join<Game, GameResult> result_theirs = game.join("results");

Так что сделайте что-то вроде ниже

CriteriaQuery<Tuple> query = cb.createTupleQuery();
Root<Game> game = query.from(Game.class);
Join<Game, GameResult> result_mine = game.join("results");
Join<Game, GameResult> result_theirs = game.join("results");
query
        .multiselect(game, result_mine, result_theirs)
        .where(
                cb.equal(result_mine.get("player"),p1),
                cb.equal(result_theirs.get("player"),p2)
        );
List<Tuple> results = em.createQuery(query).getResultList();
person Ranjeet    schedule 02.07.2017
comment
Спасибо! Я думаю, что мне не хватало того факта, что вызов game.join("results") не только возвращает объект соединения, но и мутирует сам game root, и все последовательно выполняемые соединения изменяют его (что разумно, я просто как-то не уловил). Теперь я понял (надеюсь). Теперь все работает как надо. - person Maciek; 04.07.2017