Hibernate 6 Error : Already registered a copy: SqmBasicValuedSimplePath(fullyqualifiedclass.name)

5.2k Views Asked by At

When trying to copy the Critria builder for the Count, using the existing criteria. seems getting the below error in Hibernate 6, but the same seems working in Hibernate 5.

Caused by: java.lang.IllegalArgumentException: Already registered a copy:

SqmBasicValuedSimplePath(com.example.domain.Test(175781908930100).name)

Adding the full code.

public static <Q, R> Page<Q> getResultsPage(final EntityManager entityManager, final CriteriaQuery<Q> criteria, final Root<R> root, final Pageable pageable,
            final List<Order> defaultOrderList) {
        return PageableExecutionUtils.getPage(getResultList(entityManager, criteria, root, pageable, defaultOrderList), pageable, () -> count(entityManager, criteria));
    }


public static <Q, R> List<Q> getResultList(final EntityManager entityManager, final CriteriaQuery<Q> criteria, final Root<R> root, final Pageable pageable,
            final List<Order> defaultOrderList) {
        CriteriaUtils.setOrderBy(entityManager, criteria, root, pageable, defaultOrderList);
        TypedQuery<Q> resultQuery = entityManager.createQuery(criteria);
        if (Objects.nonNull(pageable) && pageable.isPaged()) {
            resultQuery.setFirstResult((int) pageable.getOffset()).setMaxResults(pageable.getPageSize());
        }
        return resultQuery.getResultList();
    }

public static <T> Long count(EntityManager em, CriteriaQuery<T> criteria) {
        return em.createQuery(countCriteria(em, criteria)).getSingleResult();
    }

public static <T> CriteriaQuery<Long> countCriteria(EntityManager em, CriteriaQuery<T> criteria) {
        CriteriaBuilder builder = em.getCriteriaBuilder();
        CriteriaQuery<Long> countCriteria = builder.createQuery(Long.class);
        copyCriteriaWithoutSelectionAndOrder(criteria, countCriteria);

        Expression<Long> countExpression;

        if (criteria.isDistinct()) {
            countExpression = builder.countDistinct(findRoot(countCriteria, criteria.getResultType()));
        } else {
            countExpression = builder.count(findRoot(countCriteria, criteria.getResultType()));
        }

        return countCriteria.select(countExpression);
    }

private static void copyCriteriaWithoutSelectionAndOrder(
            CriteriaQuery<?> from, CriteriaQuery<?> to) {
    
        // Copy Roots
        for (Root<?> root : from.getRoots()) {
            Root<?> dest = to.from(root.getJavaType());
            dest.alias(getOrCreateAlias(root));
            copyJoins(root, dest);
        }

        to.groupBy(from.getGroupList());
        to.distinct(from.isDistinct());

        if (from.getGroupRestriction() != null)
            to.having(from.getGroupRestriction());

        Predicate predicate = from.getRestriction();
        if (predicate != null)
            to.where(predicate);
    }

1

There are 1 best solutions below

0
On

It seems that in Hibernate 6 it's no longer possible to reuse objects across different CriteriaQueries in this way. We encountered this error in CriteriaQueries where we copy the predicate from one query to another, and the fix was to refactor the code so a new Predicate object is created for each CriteriaQuery (see my answer on a similar issue). Unfortunately here it looks like it will be more difficult for you to do that - perhaps you can use the SQM copy functionality discussed here instead?