jpa 2 CriteriaQuery 不区分 child 个实体
jpa 2 CriteriaQuery do not discriminate child entities
我有一个实体,它与另一个实体存在一对多关系。说
1A -> 1.*B
我写了这个查询。
CriteriaBuilder cb = super.getEntityManager().getCriteriaBuilder();
CriteriaQuery<A> select = cb.createQuery(A.class);
Root<A> from = select.from(A.class);
Join<A, B> joinB = from.<A, B>join("b");
select.select(from);
select.where( cb.between(joinB.<Date>get("date"), dateA, dateB) );
问题: 查询返回所有 child 实体,而不是仅返回满足 between 约束的实体。
所以即使 A 有 3 个 child B 并且只有两个满足条件,查询总是 returns 3 B的。
检查休眠生成的 sql,我可以看到这个。
select a from A where a_id = ? and b_date b.date between ? and ?
很好,检索到的所有实体 A 都符合条件,但随后会引发第二个查询以获取 B 实体.
select * from b where aid = ?
这是错误的,因为 select 应该是
select * from b where aid = ? and b.date between ? and ?
我遇到过一次这个问题,但我的查询没有使用 CriteriaBuilder,使用 JOIN FETCH 解决了这个问题,但是使用 CriteriaQuery 我无法解决它。
好的,解决方案很简单(最后)我只需要添加一个从 fetch 到 join 的转换,这是最后的查询。
CriteriaBuilder cb = super.getEntityManager().getCriteriaBuilder();
CriteriaQuery<A> select = cb.createQuery(A.class);
Root<A> from = select.from(A.class);
Join<A, B> joinB = (Join<A, B>) from.<A, B>fetch("b");//CAST.
select.select(from);
select.where( cb.between(joinB.<Date>get("date"), dateA, dateB) );
我有一个实体,它与另一个实体存在一对多关系。说
1A -> 1.*B
我写了这个查询。
CriteriaBuilder cb = super.getEntityManager().getCriteriaBuilder();
CriteriaQuery<A> select = cb.createQuery(A.class);
Root<A> from = select.from(A.class);
Join<A, B> joinB = from.<A, B>join("b");
select.select(from);
select.where( cb.between(joinB.<Date>get("date"), dateA, dateB) );
问题: 查询返回所有 child 实体,而不是仅返回满足 between 约束的实体。
所以即使 A 有 3 个 child B 并且只有两个满足条件,查询总是 returns 3 B的。
检查休眠生成的 sql,我可以看到这个。
select a from A where a_id = ? and b_date b.date between ? and ?
很好,检索到的所有实体 A 都符合条件,但随后会引发第二个查询以获取 B 实体.
select * from b where aid = ?
这是错误的,因为 select 应该是
select * from b where aid = ? and b.date between ? and ?
我遇到过一次这个问题,但我的查询没有使用 CriteriaBuilder,使用 JOIN FETCH 解决了这个问题,但是使用 CriteriaQuery 我无法解决它。
好的,解决方案很简单(最后)我只需要添加一个从 fetch 到 join 的转换,这是最后的查询。
CriteriaBuilder cb = super.getEntityManager().getCriteriaBuilder();
CriteriaQuery<A> select = cb.createQuery(A.class);
Root<A> from = select.from(A.class);
Join<A, B> joinB = (Join<A, B>) from.<A, B>fetch("b");//CAST.
select.select(from);
select.where( cb.between(joinB.<Date>get("date"), dateA, dateB) );