@ManyToMany关系中表的JPA 2.0 CriteriaQuery
我在@ManyToMany
关系中有两个实体。
// Output has 4 other @ManyToOne relationships if that matters @Entity @Table public class Output { @Id public String address; @ManyToMany(targetEntity = Interval.class, cascade = CascadeType.ALL, fetch = FetchType.LAZY) @JoinTable(name = "output_has_interval", joinColumns = {@JoinColumn(name = "output_address", referencedColumnName = "address")}, inverseJoinColumns = {@JoinColumn(name = "interval_start", referencedColumnName = "start"), @JoinColumn(name = "interval_end", referencedColumnName = "end")}) Collection intervals; @IdClass(IntervalPK.class) // I'll omit this one. @Entity @Table public class Interval { @Id public Calendar start; @Id public Calendar start; @ManyToMany(targetEntity = Output.class, mappedBy = "intervals", cascade = CascadeType.ALL, fetch = FetchType.LAZY) public Collection outputs;
连接表在output
和interval
之间称为output_has_interval
。
我如何做这样的CriteriaQuery
?
SELECT `output`.`address` FROM `output`, `output_has_interval`, `interval` WHERE `output`.`address` = `output_has_interval`.`output_address` AND `interval`.`start` = `output_has_interval`.`interval_start` AND `interval`.`end` = `output_has_interval`.`interval_end` AND `interval`.`start` >= '2011-04-30'
如果我在MySQL中发布它,这可以按预期工作。
(我也有相应的静态元模型类,根据要求我可以发布它们 – 没什么好看的。)
CriteriaBuilder cb = em.getCriteriaBuilder(); CriteriaQuery cq = cb.createQuery(Output.class); Root root= cq.from(Output.class); CollectionJoin join = root.join(Output_.intervals); Expression start = join.get(Interval_.start); Predicate pred = cb.greaterThanOrEqualTo(start, /* calendar for '2011-04-30' */); cq.where(pred); TypedQuery tq = em.createQuery(cq);
但是tq.getResultList
返回数据库中的每个output
行。 任何想法?
(旁注:Hibernate(我正在使用的提供程序)在发出此查询时生成许多select
语句,每个关系Output
一个,有时更多。)
编辑:我写道:
tq.getResultList
返回数据库中的每个output
行
澄清它:它返回的不仅仅是数据库中的每个output
行。 它实际上使用output
和interval
但是谓词:
`interval`.`start` >= '2011-04-30'
不满意。
好吧,我会设法自己解决我的谜语。
首先:整个问题源于我是一个糟糕的程序员。 我迭代了TypedQuery
并以递归方式访问Output.intervals
中的每个Interval
,因此Output.intervals
懒惰地加载所请求的对象,生成一些select
语句。
但是我不得不以某种方式控制那些Interval
。 对我的CriteriaQuery
进行了以下更改。
CriteriaBuilder cb = em.getCriteriaBuilder(); CriteriaQuery cq = cb.createTupleQuery(); // or createQuery(Tuple.class) Root
编辑
我刚刚意识到我可以使用Path
对象而不是Expression
对象(反之亦然),因为Path
扩展了Expression
。 好吧…