【发布时间】:2013-12-13 01:16:00
【问题描述】:
我需要用以下实体构造一个相交类型的查询(为清楚起见,减少了)。
@Entity // and other @ stuff
public class Member {
@Id
private Long id;
private String name;
...
}
@Entity
public class Program {
@Id
private Long id;
private Long programName;
private List<ProgramLevel> levels;
...
}
@Entity
public class ProgramLevel {
@Id
private Long id
private String levelName;
}
一个成员可以属于一个或多个程序,并且他总是有自己的程序级别,通过以下方式连接:
public class Membership {
@Id
private Long id;
private Long memberId; // this is the member
private Long programId; // in which program is he
private Long programLevel; // and on what level
...
}
示例:我有三个课程,数学、英语、科学。他们每个人都有一些级别,比如,数学有代数、几何,英语有文学、拼写和语法,科学有实验和理论。
此外,示例用户 Joe 将拥有数学:代数、英语:语法程序和级别。示例用户 Max 可能有 English:literature。因此,会员可以拥有多个计划,但每个计划只有一个级别。
现在我需要计算或获取与一些程序和其中一些级别匹配的所有成员。 示例:我希望所有拥有数学:代数或几何、英语:文学或语法和科学:理论的用户。
我不是很喜欢 JPA 的东西,所以我被卡住了。
在 SQL 中,我会做一个相交。我将如何使用 JPA?
我有这样的事情:
HashMap<Long, List<ProgramLevel>> levels = new HashMap<Long, List<ProgramLevel>>();
// then I fetch the levels map.
CriteriaBuilder cb = entityManager.getCriteriaBuilder();
CriteriaQuery<Long> criteriaQuery = cb.createQuery(Long.class);
Root<Membership> root = query.from(Membership.class);
// this is the part where I'm stuck.
// I figured I could try with multiple inner joins?
for(Map.Entry<Long, List<ProgramLevel>> curentLevel: levels.entrySet()) {
// cb.equal(root.join ??? what comes here?
// what what what?
// root.get("programId") = currentLevel.getKey()
// AND root.get("programLevelId") IN currentLevel.getValue()
}
...
我怎么会得到这个?
除了作为多个内部连接之外,我不知道它是否可以作为 INTERSECT 来完成(如果重要,db 是 PostgreSQL)?
另外,我不确定我会在该查询中的哪个位置放置条件,以便仅在这些条件下让我获得不同的成员资格。
作为奖励,我必须创建一个 OR 查询。这个是我必须匹配所有程序的地方,下一个需要任何程序/级别匹配才能将成员包括在内。但是,一旦我想出了这个,我希望我会自己想出那个。
编辑:可能的(伪)SQL 选择如下所示:
SELECT count(membership) FROM membership m
WHERE (m.program == :program1 and m.programLevel in :programLevels1ArrayOfLevels)
INTERSECT
SELECT count(membership) FROM membership m
WHERE (m.program == :program2 and m.programLevel in :programLevels2ArrayOfLevels)
INTERSECT...
... /* this would go on for as many (Program, List<ProgramLevel>) pairs I have on input. Which is variable).
或者是这样的:
SELECT count(membership) FROM membership m
JOIN membership m1 ON (m1.program = :program1 AND m1.programLevel IN m1.programLevels1Aray)
JOIN membership m2 ON (m2.program = :program2 AND m2.programLevel IN m1.programLevels2Aray)
/* Continued to as many input pairs I have */
【问题讨论】:
-
您通常会通过使用不同别名多次连接同一个表来做到这一点。 JPA 应该提供一种方法来做到这一点,但我很高兴大约一年来不必使用它或它的 Criteria API,所以我要为你指出大致正确的方向,然后尖叫着逃往山上。
-
嗯。我将如何命名这些连接?因为我不知道他们有多少人。我不知道它是否显示,但 Java 是我的第二语言 :)
-
@AnthonyAccioly 我已经更新了问题,在那里添加了一些 SQL 以显示我想要的内容。
标签: java postgresql jpa join intersect