Skip to content

DTO Projection JPQL Query Rewriting breaks interoperability for custom basic hibernate types #4128

@joshiste

Description

@joshiste

We're a bit late in upgrading to Spring Data JPA 3.5.7 (coming from 3.4.13).

We have a custom type TeamId (which is simply a wrapper around UUID) and have registered a basic type for this in Hibernate, using it for our ID columns. Therefore, it also appears as a return type on query methods.
With 3.4.x this was working perfectly fine.

With 3.5.x, the return type is incorrectly recognized as a DTO, and the DtoProjectionTransformerDelegate rewrites the query to use a constructor expression.
This is unnecessary, as the value returned by Hibernate is a TeamId. This also causes the exception below (output shortened) because it cannot find an appropriate constructor.

I could not find any option in the docs to disable that feature or to exclude specific types from it. I'd like to have some option for this.

org.springframework.dao.InvalidDataAccessApiUsageException: org.hibernate.query.SemanticException: Missing constructor for type 'TeamId' [select distinct new com.steadybit.platform.server.common.identifiers.TeamId(t.id) from Team t join t.members m where m.username = :username and m.role = :role]
        at org.springframework.orm.jpa.EntityManagerFactoryUtils.convertJpaAccessExceptionIfPossible(EntityManagerFactoryUtils.java:371)
        at org.springframework.orm.jpa.vendor.HibernateJpaDialect.translateExceptionIfPossible(HibernateJpaDialect.java:246)
        at org.springframework.orm.jpa.AbstractEntityManagerFactoryBean.translateExceptionIfPossible(AbstractEntityManagerFactoryBean.java:560)
        at org.springframework.dao.support.ChainedPersistenceExceptionTranslator.translateExceptionIfPossible(ChainedPersistenceExceptionTranslator.java:61)
        at org.springframework.dao.support.DataAccessUtils.translateIfNecessary(DataAccessUtils.java:343)
        at org.springframework.dao.support.PersistenceExceptionTranslationInterceptor.invoke(PersistenceExceptionTranslationInterceptor.java:160)
        at org.springframework.aop.framework.ReflectiveMethodInvocation.proceed(ReflectiveMethodInvocation.java:184)
        at org.springframework.data.jpa.repository.support.CrudMethodMetadataPostProcessor$CrudMethodMetadataPopulatingMethodInterceptor.invoke(CrudMethodMetadataPostProcessor.java:136)
        at org.springframework.aop.framework.ReflectiveMethodInvocation.proceed(ReflectiveMethodInvocation.java:184)
        at org.springframework.aop.framework.JdkDynamicAopProxy.invoke(JdkDynamicAopProxy.java:223)
        at jdk.proxy2/jdk.proxy2.$Proxy282.findTeamIdsWithRoleAndUsername(Unknown Source)
        at java.base/jdk.internal.reflect.DirectMethodHandleAccessor.invoke(DirectMethodHandleAccessor.java:103)
        at java.base/java.lang.reflect.Method.invoke(Method.java:580)
        at org.springframework.aop.support.AopUtils.invokeJoinpointUsingReflection(AopUtils.java:360)
        at org.springframework.aop.framework.JdkDynamicAopProxy.invoke(JdkDynamicAopProxy.java:216)
        at jdk.proxy2/jdk.proxy2.$Proxy282.findTeamIdsWithRoleAndUsername(Unknown Source)
        at com.steadybit.platform.server.teams.domain.TeamService.findTeamIdsWithRole(TeamService.java:547)
        at java.base/jdk.internal.reflect.DirectMethodHandleAccessor.invoke(DirectMethodHandleAccessor.java:103)
        at java.base/java.lang.reflect.Method.invoke(Method.java:580)
 ...
Caused by: org.hibernate.query.SemanticException: Missing constructor for type 'TeamId' [select distinct new com.steadybit.platform.server.common.identifiers.TeamId(t.id) from Team t join t.members m where m.username = :username and m.role = :role]
        at org.hibernate.query.hql.internal.SemanticQueryBuilder.visitInstantiation(SemanticQueryBuilder.java:1504)
        at org.hibernate.query.hql.internal.SemanticQueryBuilder.visitInstantiation(SemanticQueryBuilder.java:278)
        at org.hibernate.grammars.hql.HqlParser$InstantiationContext.accept(HqlParser.java:3977)
        at org.hibernate.query.hql.internal.SemanticQueryBuilder.visitSelectableNode(SemanticQueryBuilder.java:1451)
        at org.hibernate.query.hql.internal.SemanticQueryBuilder.visitSelection(SemanticQueryBuilder.java:1405)
        at org.hibernate.query.hql.internal.SemanticQueryBuilder.visitSelectClause(SemanticQueryBuilder.java:1398)
...

Metadata

Metadata

Assignees

No one assigned

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions