Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

QueryTypeMismatchException if the DTO has a no-args constructor #3216

Closed
jhs512 opened this issue Dec 30, 2023 · 2 comments
Closed

QueryTypeMismatchException if the DTO has a no-args constructor #3216

jhs512 opened this issue Dec 30, 2023 · 2 comments
Assignees
Labels
type: documentation A documentation update

Comments

@jhs512
Copy link

jhs512 commented Dec 30, 2023

PostRepository.java

package com.ll.medium.domain.post.post.repository;

import com.ll.medium.domain.member.member.entity.Member;
import com.ll.medium.domain.post.post.entity.Post;
import org.springframework.data.domain.Page;
import org.springframework.data.domain.Pageable;
import org.springframework.data.jpa.repository.JpaRepository;

import java.util.List;
import java.util.Optional;

public interface PostRepository extends JpaRepository<Post, Long> {
    <T> Optional<T> findTop1ByOrderByIdDesc(Class<T> type);
}

Post.java

package com.ll.medium.domain.post.post.entity;

import com.ll.medium.domain.member.member.entity.Member;
import com.ll.medium.global.jpa.BaseTime.BaseTime;
import jakarta.persistence.Entity;
import jakarta.persistence.ManyToOne;
import lombok.*;

@Entity
@Builder
@NoArgsConstructor(access = AccessLevel.PROTECTED)
@AllArgsConstructor(access = AccessLevel.PROTECTED)
@Getter
@Setter
@EntityListeners(AuditingEntityListener.class)
@EqualsAndHashCode(onlyExplicitlyIncluded = true)
public class Post extends BaseTime {
    @Id
    @GeneratedValue(strategy = IDENTITY)
    @EqualsAndHashCode.Include
    private Long id;
    @CreatedDate
    private LocalDateTime createDate;
    @LastModifiedDate
    private LocalDateTime modifyDate;
    @ManyToOne
    private Member author;
    private String title;
    private String body;
    private boolean published;
}

PostDtoImpl.java

@Getter
@Setter
@NoArgsConstructor // When this annotation is present, the following error occurs
@AllArgsConstructor
public class PostDtoImpl {
    private long id;
    private LocalDateTime createDate;
    private LocalDateTime modifyDate;
    private long authorId;
    private String authorUsername;
    private String title;
    private String body;
    private boolean published;
}

Error Msg

org.hibernate.query.QueryTypeMismatchException: Specified result type [com.ll.medium.domain.post.post.dto.PostDto] did not match Query selection type [com.ll.medium.domain.post.post.entity.Post] - multiple selections: use Tuple or array
	at org.hibernate.query.spi.AbstractSelectionQuery.throwQueryTypeMismatchException(AbstractSelectionQuery.java:412) ~[hibernate-core-6.4.1.Final.jar:6.4.1.Final]
	at org.hibernate.query.spi.AbstractSelectionQuery.verifyResultType(AbstractSelectionQuery.java:353) ~[hibernate-core-6.4.1.Final.jar:6.4.1.Final]
	at org.hibernate.query.spi.AbstractSelectionQuery.checkQueryReturnType(AbstractSelectionQuery.java:318) ~[hibernate-core-6.4.1.Final.jar:6.4.1.Final]
	at org.hibernate.query.spi.AbstractSelectionQuery.visitQueryReturnType(AbstractSelectionQuery.java:283) ~[hibernate-core-6.4.1.Final.jar:6.4.1.Final]
	at org.hibernate.query.sqm.internal.QuerySqmImpl.<init>(QuerySqmImpl.java:268) ~[hibernate-core-6.4.1.Final.jar:6.4.1.Final]
	at org.hibernate.internal.AbstractSharedSessionContract.createCriteriaQuery(AbstractSharedSessionContract.java:1407) ~[hibernate-core-6.4.1.Final.jar:6.4.1.Final]
	at org.hibernate.internal.AbstractSharedSessionContract.createQuery(AbstractSharedSessionContract.java:1367) ~[hibernate-core-6.4.1.Final.jar:6.4.1.Final]
	at org.hibernate.internal.AbstractSharedSessionContract.createQuery(AbstractSharedSessionContract.java:133) ~[hibernate-core-6.4.1.Final.jar:6.4.1.Final]
	at java.base/jdk.internal.reflect.DirectMethodHandleAccessor.invoke(DirectMethodHandleAccessor.java:103) ~[na:na]
	at java.base/java.lang.reflect.Method.invoke(Method.java:580) ~[na:na]
	at org.springframework.orm.jpa.ExtendedEntityManagerCreator$ExtendedEntityManagerInvocationHandler.invoke(ExtendedEntityManagerCreator.java:364) ~[spring-orm-6.1.2.jar:6.1.2]
	at jdk.proxy4/jdk.proxy4.$Proxy150.createQuery(Unknown Source) ~[na:na]
	at java.base/jdk.internal.reflect.DirectMethodHandleAccessor.invoke(DirectMethodHandleAccessor.java:103) ~[na:na]
	at java.base/java.lang.reflect.Method.invoke(Method.java:580) ~[na:na]
	at org.springframework.orm.jpa.SharedEntityManagerCreator$SharedEntityManagerInvocationHandler.invoke(SharedEntityManagerCreator.java:319) ~[spring-orm-6.1.2.jar:6.1.2]
	at jdk.proxy4/jdk.proxy4.$Proxy150.createQuery(Unknown Source) ~[na:na]
	at org.springframework.data.jpa.repository.query.PartTreeJpaQuery$QueryPreparer.createQuery(PartTreeJpaQuery.java:301) ~[spring-data-jpa-3.2.1.jar:3.2.1]
	at org.springframework.data.jpa.repository.query.PartTreeJpaQuery$QueryPreparer.createQuery(PartTreeJpaQuery.java:242) ~[spring-data-jpa-3.2.1.jar:3.2.1]
	at org.springframework.data.jpa.repository.query.PartTreeJpaQuery.doCreateQuery(PartTreeJpaQuery.java:113) ~[spring-data-jpa-3.2.1.jar:3.2.1]
	at org.springframework.data.jpa.repository.query.AbstractJpaQuery.createQuery(AbstractJpaQuery.java:239) ~[spring-data-jpa-3.2.1.jar:3.2.1]
	at org.springframework.data.jpa.repository.query.JpaQueryExecution$SingleEntityExecution.doExecute(JpaQueryExecution.java:223) ~[spring-data-jpa-3.2.1.jar:3.2.1]
	at org.springframework.data.jpa.repository.query.JpaQueryExecution.execute(JpaQueryExecution.java:92) ~[spring-data-jpa-3.2.1.jar:3.2.1]
	at org.springframework.data.jpa.repository.query.AbstractJpaQuery.doExecute(AbstractJpaQuery.java:149) ~[spring-data-jpa-3.2.1.jar:3.2.1]
	at org.springframework.data.jpa.repository.query.AbstractJpaQuery.execute(AbstractJpaQuery.java:137) ~[spring-data-jpa-3.2.1.jar:3.2.1]
	at org.springframework.data.repository.core.support.RepositoryMethodInvoker.doInvoke(RepositoryMethodInvoker.java:170) ~[spring-data-commons-3.2.1.jar:3.2.1]
	at org.springframework.data.repository.core.support.RepositoryMethodInvoker.invoke(RepositoryMethodInvoker.java:158) ~[spring-data-commons-3.2.1.jar:3.2.1]
	at org.springframework.data.repository.core.support.QueryExecutorMethodInterceptor.doInvoke(QueryExecutorMethodInterceptor.java:164) ~[spring-data-commons-3.2.1.jar:3.2.1]
	at org.springframework.data.repository.core.support.QueryExecutorMethodInterceptor.invoke(QueryExecutorMethodInterceptor.java:143) ~[spring-data-commons-3.2.1.jar:3.2.1]
	at org.springframework.aop.framework.ReflectiveMethodInvocation.proceed(ReflectiveMethodInvocation.java:184) ~[spring-aop-6.1.2.jar:6.1.2]
	at org.springframework.data.projection.DefaultMethodInvokingMethodInterceptor.invoke(DefaultMethodInvokingMethodInterceptor.java:70) ~[spring-data-commons-3.2.1.jar:3.2.1]
	at org.springframework.aop.framework.ReflectiveMethodInvocation.proceed(ReflectiveMethodInvocation.java:184) ~[spring-aop-6.1.2.jar:6.1.2]
	at org.springframework.transaction.interceptor.TransactionInterceptor$1.proceedWithInvocation(TransactionInterceptor.java:123) ~[spring-tx-6.1.2.jar:6.1.2]
	at org.springframework.transaction.interceptor.TransactionAspectSupport.invokeWithinTransaction(TransactionAspectSupport.java:385) ~[spring-tx-6.1.2.jar:6.1.2]
	at org.springframework.transaction.interceptor.TransactionInterceptor.invoke(TransactionInterceptor.java:119) ~[spring-tx-6.1.2.jar:6.1.2]
	at org.springframework.aop.framework.ReflectiveMethodInvocation.proceed(ReflectiveMethodInvocation.java:184) ~[spring-aop-6.1.2.jar:6.1.2]
	at org.springframework.dao.support.PersistenceExceptionTranslationInterceptor.invoke(PersistenceExceptionTranslationInterceptor.java:137) ~[spring-tx-6.1.2.jar:6.1.2]
	at org.springframework.aop.framework.ReflectiveMethodInvocation.proceed(ReflectiveMethodInvocation.java:184) ~[spring-aop-6.1.2.jar:6.1.2]
	at org.springframework.data.jpa.repository.support.CrudMethodMetadataPostProcessor$CrudMethodMetadataPopulatingMethodInterceptor.invoke(CrudMethodMetadataPostProcessor.java:135) ~[spring-data-jpa-3.2.1.jar:3.2.1]
	at org.springframework.aop.framework.ReflectiveMethodInvocation.proceed(ReflectiveMethodInvocation.java:184) ~[spring-aop-6.1.2.jar:6.1.2]
	at org.springframework.aop.interceptor.ExposeInvocationInterceptor.invoke(ExposeInvocationInterceptor.java:97) ~[spring-aop-6.1.2.jar:6.1.2]
	at org.springframework.aop.framework.ReflectiveMethodInvocation.proceed(ReflectiveMethodInvocation.java:184) ~[spring-aop-6.1.2.jar:6.1.2]
	at org.springframework.aop.framework.JdkDynamicAopProxy.invoke(JdkDynamicAopProxy.java:249) ~[spring-aop-6.1.2.jar:6.1.2]
	at jdk.proxy4/jdk.proxy4.$Proxy159.findTop1ByAuthorAndPublishedAndTitleOrderByIdDesc(Unknown Source) ~[na:na]
	at com.ll.medium.domain.post.post.service.PostService.findTempOrMake(PostService.java:61) ~[main/:na]
	at java.base/jdk.internal.reflect.DirectMethodHandleAccessor.invoke(DirectMethodHandleAccessor.java:103) ~[na:na]
	at java.base/java.lang.reflect.Method.invoke(Method.java:580) ~[na:na]
@jhs512 jhs512 changed the title Bug Report : List<PostDto> list = postRepository.findTop1ByOrderByIdDesc(PostDto.class); // If the PostDto class has a no-argument constructor, an error occurs here. Bug Report : List<PostDto> list = postRepository.findTop1ByOrderByIdDesc(PostDto.class); // If the PostDto class has a no-argument constructor, an error occurs. Dec 30, 2023
@spring-projects-issues spring-projects-issues added the status: waiting-for-triage An issue we've not yet triaged label Dec 30, 2023
@christophstrobl christophstrobl self-assigned this Jan 8, 2024
@christophstrobl
Copy link
Member

Thank you for reporting the issue - we'll have a look what's going on there.

@christophstrobl
Copy link
Member

DTO based projections try to resolve the properties to load from the DTOs constructor, whereas the lookup is defined as outlined in the reference documentation. In this case the no-args constructor is picked, which in turn triggers an attempt to use the source Root in the actual select which is then causing the error.
I've to admit that the documentation around DTO based projections does not mention this scenario.

For the time being please provide only one constructor defining the properties to project onto or make use of the @PersistenceCreator annotation.

Going forward, we've are discussing a potential enhancement to the projection flow of data-jpa to cover the use case described above using available setter methods to determine the fields to load.

@mp911de mp911de added type: documentation A documentation update and removed status: waiting-for-triage An issue we've not yet triaged labels Jan 22, 2024
christophstrobl referenced this issue in spring-projects/spring-data-jpa Apr 26, 2024
For the time being we at least now document the current behaviour and how to cope with it.

See: #3286
christophstrobl referenced this issue in spring-projects/spring-data-jpa Apr 26, 2024
For the time being we at least now document the current behaviour and how to cope with it.

See: #3286
@mp911de mp911de assigned mp911de and unassigned christophstrobl Dec 3, 2024
@mp911de mp911de changed the title Bug Report : List<PostDto> list = postRepository.findTop1ByOrderByIdDesc(PostDto.class); // If the PostDto class has a no-argument constructor, an error occurs. QueryTypeMismatchException if the DTO has a no-args constructor Dec 3, 2024
@mp911de mp911de added this to the 3.3.7 (2024.0.7) milestone Dec 3, 2024
mp911de referenced this issue in spring-projects/spring-data-jpa Dec 3, 2024
For the time being we at least now document the current behaviour and how to cope with it.

Closes: #3286
Original pull request: #3449
mp911de referenced this issue in spring-projects/spring-data-jpa Dec 3, 2024
Tweak wording.

See: #3286
Original pull request: #3449
mp911de referenced this issue in spring-projects/spring-data-jpa Dec 3, 2024
Tweak wording.

See: #3286
Original pull request: #3449
mp911de referenced this issue in spring-projects/spring-data-jpa Dec 3, 2024
For the time being we at least now document the current behaviour and how to cope with it.

Closes: #3286
Original pull request: #3449
mp911de referenced this issue in spring-projects/spring-data-jpa Dec 3, 2024
Tweak wording.

See: #3286
Original pull request: #3449
@mp911de mp911de transferred this issue from spring-projects/spring-data-jpa Dec 3, 2024
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
type: documentation A documentation update
Projects
None yet
Development

Successfully merging a pull request may close this issue.

4 participants