Запрос по критерию JPA 2 с гибернацией не удается соединиться слева

В моем приложении у меня есть роли, которые имеют разрешения, я использовал для этого:

   Query query =
        em.createQuery(
            "SELECT distinct r FROM Role r left join fetch r.permissions "
            + "where r.domain = ? " + "order by r.createdOn ").setParameter(
            1, domain);

    return query.getResultList();

Но хотел более тонкий контроль над ленивыми инициализациями. Поэтому я пытаюсь это сделать, но это не работает, потому что соединение выполняется так, как если бы оно было внутренним объединением, не принося одну роль и ее разрешения, но один результат на строку и на разрешение тоже.

public List<Role> findAll()
{
    CriteriaBuilder criteriaBuilder;
    CriteriaQuery<Role> criteriaQuery;
    Root<Role> queryRoot;
    Order createdOnDesc;
    TypedQuery<Role> typedQuery;
    List<Role> roleResultList;

    //initialize query system
    criteriaBuilder = em.getCriteriaBuilder();

    //select * from Role
    criteriaQuery = criteriaBuilder.createQuery(Role.class);
    queryRoot = criteriaQuery.from(Role.class);

    //join permissions by default "LEFT"
    //***THIS LINE IS FAILING*** ????
    queryRoot.join(Role_.permissions);

    //get query
    typedQuery = em.createQuery(criteriaQuery);

    //the steps below must be done to avoid lazy initialization exceptions
    //in case we want to access the list at a later time
    roleResultList = typedQuery.getResultList();

    for (Role role : roleResultList)
    {
        role.getPermissionsList();
    }

    return roleResultList;
}

Любые мысли или идеи будут высоко оценены.

1 ответ

Решение

Мне немного непонятно, чего ты хочешь достичь, но, возможно, следование поможет в любом случае.

По умолчанию это внутреннее соединение, как сказано в API.

//join permissions by default "LEFT"
//***THIS LINE IS FAILING*** ????
queryRoot.join(Role_.permissions);

Если вам нужно что-то похожее на оригинальный запрос JPQL, это можно сделать с помощью fetch. Если вы хотите использовать левое (внешнее) соединение вместо этого, это можно сделать с помощью метода соединения, который принимает JoinType в качестве аргумента:

queryRoot.join(Role_.permissions, JoinType.LEFT);

Когда нужны разные результаты, тогда CriteriaQuery.distinct полезен.

Другие вопросы по тегам