jpa 2 标准 hibernate 5.2 嵌套连接

jpa 2 criteria hibernate 5.2 nested joins

我正在尝试为我的 crud 服务添加指定我需要的嵌套关系的可能性,这样我就不必从数据库中读取所有内容。

比如我有那些实体

Company.java

private List<Department> departments;
private SalaryCode salaryCode;

Department.java

private List<Employee> employees;
private Company company;
private SalaryCode salaryCode;

Employee.java

private Department department;
private SalaryCode salaryCode

我现在的条件查询是这样的:

Session session = sessionFactory.openSession();
CriteriaBuilder builder = session.getCriteriaBuilder();
CriteriaQuery<T> criteriaQuery = builder.createQuery(clazz);
Root<T> root = criteriaQuery.from(clazz);

//nestedRelationships is a varargs passed as parameters
for(String nestedRelationship : nestedRelationships) {
    root.fetch(nestedRelationship, JoinType.LEFT);
}

List<T> result = session.createQuery(criteriaQuery.select(root)).list();

问题是,如果我将 "department" 指定为 nestedRelationship 并查询 Employee 实体,它运行良好,但是当我尝试指定 "department.salaryCode" 时,它不起作用,提示“无法使用给定的名称”。 当然我先取 "department" 然后 "department.salaryCode".

是否支持?如果是,它是如何工作的?如果不支持我该怎么办?

是的,支持。您需要使用联接。

    Root<Company> root = criteriaQuery.from(Company.class);
    Join<Company,Department> joinDepartment = root.join( Company_.departments );
    Join<Department,SalaryCode> joinSalaryCode = joinDepartment.join( Department_.salaryCode );

要生成元模型 类(例如 Department_ )请查看 here.

我通过使用根元素制定算法找到了解决方案

protected void fetch(Root<T> root, String... joins) {
    //Sort the joins so they are like this :
    //A
    //A.F
    //B.E
    //B.E.D
    //B.G
    Arrays.sort(joins);

    Map<String, Fetch> flattenFetches = new HashMap<>();

    for (String join : joins) {
        try {
            if (join.contains(".")) {
                String[] subrelations = join.split("\.");
                Fetch lastRelation = null;
                int i;

                for (i = subrelations.length - 1; i >= 0; i--) {
                    String subJoin = String.join(".", Arrays.copyOf(subrelations, i));

                    if (flattenFetches.containsKey(subJoin)) {
                        lastRelation = flattenFetches.get(subJoin);
                        break;
                    }
                }

                if (lastRelation == null) {
                    lastRelation = root.fetch(subrelations[0], JoinType.LEFT);
                    flattenFetches.put(subrelations[0], lastRelation);
                    i = 1;
                }

                for (; i < subrelations.length; i++) {
                    String relation = subrelations[i];
                    String path = String.join(".", Arrays.copyOf(subrelations, i + 1));

                    if (i == subrelations.length - 1) {
                        Fetch fetch = lastRelation.fetch(relation, JoinType.LEFT);
                        flattenFetches.put(path, fetch);
                    } else {
                        lastRelation = lastRelation.fetch(relation, JoinType.LEFT);
                        flattenFetches.put(path, lastRelation);
                    }
                }
            } else {
                Fetch fetch = root.fetch(join, JoinType.LEFT);
                flattenFetches.put(join, fetch);
            }
        } catch (Exception e) {
            e.printStackTrace();
        }
    }
}

要使用它,我只需要做例如:

employeeController.getAll("punches", "currentSchedule.shifts", "defaultDepartment.currentSchedule.shifts",
            "defaultDepartment.company.currentSchedule.shifts", "bankExtras")

我想评论算法但我没有时间而且它很容易理解