使用JPA Criteria,如何在不获取Joined实体的情况下获取Joined实体的子实体?

时间:2016-11-18 21:40:15

标签: java hibernate criteria hibernate-criteria criteria-api

在我的项目中,我使用Groovy和Spring Data JPA' Specification来构建Hibernate查询。

我无法提供实际查询,但为了说明我的问题,我们说我有建筑实体,每栋楼都有楼层,每层都有房间和Windows。

我尝试模拟的行为类似于本机SQL查询:

SELECT b.*, r.*
FROM building b
INNER JOIN floor f ON b.id = f.building_id
INNER JOIN window w ON f.id = w.floor_id
LEFT OUTER JOIN room r ON f.id = r.floor_id
WHERE w.id = 1;

我有类似下面的规范:

public class MySpec implements Specification<Building> {
    @Override
    public Predicate toPredicate(final Root<Building> root, final CriteriaQuery<?> query, final CriteriaBuilder cb) {
        final Join floorsJoin = root.join("floors");
        final Join windowsJoin = floorsJoin.join("windows");

        //I'd like to remove this line
        final Fetch floorsFetch = root.fetch("floors"); // <---

        floorsFetch.fetch("rooms", JoinType.LEFT);

        cb.equal(windowsJoin.get("id"), 1L);
    }
}

上面注释的是我的问题。如果我离开它,生成的查询看起来像这样:

SELECT b.*, f2.*, r.*
FROM building b
INNER JOIN floor f ON b.id = f.building_id
INNER JOIN window w ON f.id = w.floor_id
INNER JOIN floor f2 ON b.id = f2.building_id
LEFT OUTER JOIN room r ON f2.id = r.floor_id
WHERE w.id = 1;

(请注意INNER JOIN的重复floor和不需要的f2.*数据

如果我删除它,并使用floorsJoin代替获取房间,我会收到以下Hibernate错误:

org.hibernate.QueryException: query specified join fetching, but the owner of the fetched association was not present in the select list

不需要的f2.*数据可以,但我无法用floorsJoin替换上述floorsFetch,因为我需要加入windows表格(不提取windows)且Fetch类没有.join方法。

我很难搞清楚如何在仍然生成单个查询的同时完成我需要的工作;当然,我必须遗漏一些简单的东西。

您可以提供的任何想法或建议都会非常感激。

非常感谢, B.J。

1 个答案:

答案 0 :(得分:0)

使用JPA Criteria API并不是那么简单。使用Hibernate,您可以简单地将public View onCreateView(...) { rootView = inflater.inflate(...); listView = ...; listView.setOnTouchListner(... @Override public boolean onTouch(View v, MotionEvent event) { return false; // Says that click was not handled here. } }); rootView.setOnTouchListner(... // TODO: Check if click landed outside the ListView @Override public boolean onTouch(View v, MotionEvent event) { if (v.getId() != android.R.id.listView) { // Not the list if (event.getAction() == MotionEvent.ACTION_UP) { // Up action more reliable than "down" return true; } } } ); return rootView; } 转换为Fetch我猜,但这对您没那么大帮助。我不确定你在这种情况下如何使用规范,但如果你可以整体编写查询,它可能如下所示

Join