We would like to use a DTO projection over the interface one, thus we created following DTO objects:
PersonDto
@Data
@Builder
@AllArgsConstructor
public class PersonDto {
private String name;
private String email;
private AddressDto address;
}
AddressDto
@Data
@Builder
@AllArgsConstructor
public class AddressDto {
private String address;
private String streetNumber;
}
A repository
@Repository
public interface PersonRepository extends JpaRepository<PersonEntity, Long> {
List<PersonDto> findAllDtoedBy();
}
However, when called we get the exception:
Caused by: org.hibernate.hql.internal.ast.QuerySyntaxException: Unable to locate appropriate constructor on class [com.example.projections.model.PersonDto]. Expected arguments are: java.lang.String, java.lang.String, com.example.projections.model.AddressEntity [select new com.example.projections.model.PersonDto(generatedAlias0.name, generatedAlias0.email, address) from com.example.projections.model.PersonEntity as generatedAlias0 left join generatedAlias0.address as address]
at org.hibernate.hql.internal.ast.QuerySyntaxException.convert(QuerySyntaxException.java:74) ~[hibernate-core-5.2.11.Final.jar:5.2.11.Final]
at org.hibernate.hql.internal.ast.ErrorCounter.throwQueryException(ErrorCounter.java:91) ~[hibernate-core-5.2.11.Final.jar:5.2.11.Final]
at org.hibernate.hql.internal.ast.QueryTranslatorImpl.analyze(QueryTranslatorImpl.java:272) ~[hibernate-core-5.2.11.Final.jar:5.2.11.Final]
at org.hibernate.hql.internal.ast.QueryTranslatorImpl.doCompile(QueryTranslatorImpl.java:189) ~[hibernate-core-5.2.11.Final.jar:5.2.11.Final]
Note the line: "...Expected arguments are: java.lang.String, java.lang.String, com.example.projections.model.AddressEntity...".
Obviously it expects the model object AddressEntity, and gets confused when a DTO object (AddressDto) is found instead.
So the question is, since this works with the interface projection, we would expect this to be supported by a DTO projection as well? By looking at the samples on GitHub (https://github.com/spring-projects/spring-data-examples/blob/master/jpa/example/src/main/java/example/springdata/jpa/projections/CustomerRepository.java) and in the Spring Data JPA documentation, we didn't see an example for this case, but we also din't see an explicit statement that this isn't supported
You define a DTO projection in a CriteriaQuery in a pretty similar way as you do in JPQL. But instead of using the new keyword to specify the constructor call in a query String, you call the construct method on the CriteriaBuilder with a reference to the DTO class and a List of constructor parameters.
Spring Data JPA doesn't provide an automatic mapping of class-based DTOs for native queries. The easiest way to use this projection is to define your query as a @NamedNativeQuery and assign an @SqlResultSetMapping that defines a constructor result mapping.
Fetching a one-to-many DTO projection with JPA and Hibernate. The postDTOMap is where we are going to store all PostDTO entities that, in the end, will be returned by the query execution. The reason we are using the postDTOMap is that the parent rows are duplicated in the SQL query result set for each child record.
From Spring Data JPA - Reference Documentation:
Another way of defining projections is using value type DTOs that hold properties for the fields that are supposed to be retrieved. These DTO types can be used exactly the same way projection interfaces are used, except that no proxying is going on here and no nested projections can be applied.
I think the reason is this...
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With