JPA Criteria API 和同一路径表达式上的两个连接
JPA Criteria API and two joins on the same path expression
我的问题与这个老问题非常相似: 但我需要一个非 Hibernate 特定的、干净的 JPA 解决方案来解决相同的问题。我目前使用 Hibernate 4.3 作为 JPA 提供程序,但如果需要我可以更新它。我有以下实体:
- 游戏,它可以有很多 Result 条目,每个玩家一个
- GameResult 由 Game 拥有并引用了参与其中的玩家。它没有对拥有 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 查询转换为 Criteria API 代码?
你的第 3 个或是正确的,除非你加入了两次
您的行 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();
我的问题与这个老问题非常相似:
- 游戏,它可以有很多 Result 条目,每个玩家一个
- GameResult 由 Game 拥有并引用了参与其中的玩家。它没有对拥有 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 查询转换为 Criteria API 代码?
你的第 3 个或是正确的,除非你加入了两次
您的行 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();