@RequestMapping(value = "deadlinetype")
@RestController
public class DeadlineTypeController {
private final ABDeadlineTypeRepository abDeadlineTypeRepository;
@Autowired
public DeadlineTypeController(ABDeadlineTypeRepository abDeadlineTypeRepository) {
this.abDeadlineTypeRepository = abDeadlineTypeRepository;
@GetMapping(value = "/list")
public ResponseEntity<List<ABDeadlineType>> list() {
List<ABDeadlineType> types = abDeadlineTypeRepository.findAll();
return ResponseEntity.ok(types);
@GetMapping(value = "/listdto")
public ResponseEntity<List<DeadlineType>> listDto() {
List<DeadlineType> types = abDeadlineTypeRepository.findAllDtoBy();
return ResponseEntity.ok(types);
@GetMapping(value = "/listprojection")
public ResponseEntity<List<DeadlineTypeProjection>> listProjection() {
List<DeadlineTypeProjection> types = abDeadlineTypeRepository.findAllProjectionBy();
return ResponseEntity.ok(types);
Hope that helps
–
I have met the same problem recently with spring-data-jpa:2.5.0.
Solution (for queries with no @Query annotation):
For class-based projection (DTOs), the problem is the @NoArgsConstructor
in the DTO class. Revemoving it should make things work.
Something interesting I found during debug:
With the presence of a non argument constructor, the returnedType
somehow was created with 0 input properties.
When a query is actually created, JpaQueryCreator
(spring-data-jpa) would check if it needs to do custom construction according to the number of input properties.
As it's not the case with 0 input properties, it would then return the whole entity instance.
https://github.com/spring-projects/spring-data-jpa/blob/main/src/main/java/org/springframework/data/jpa/repository/query/JpaQueryCreator.java#L169
Finally when the result is being returned, the target type and returned type don't match, as there is no converter available to convert from the entity instance to the projectiong dto. The error was thrown.
https://github.com/spring-projects/spring-data-commons/blob/main/src/main/java/org/springframework/data/repository/query/ResultProcessor.java#L162
–
–
use {nativeQuery=true} in your query.
for example
@Query(value = "select d.id,d.name,d.breed,d.origin from Dog d",nativeQuery = true)
List<Dog> findALL();
If you look at the exception stack trace it says that, it failed to convert from ABDeadlineType
to DeadlineType
. Because your repository is going to return you the objects of ABDeadlineType
. How the spring-data-jpa
will convert into the other one(DeadlineType
). You should return the same type from repository and then have some intermediate util class to convert it into your model class.
public interface ABDeadlineTypeRepository extends JpaRepository<ABDeadlineType, Long> {
List<ABDeadlineType> findAllSummarizedBy();
Turns out, when the table name is different than the model name, you have to change the annotations to:
@Entity
@Table(name = "table_name")
class WhateverNameYouWant {
Instead of simply using the @Entity annotation.
What was weird for me, is that the class it was trying to convert to didn't exist. This worked for me.
If you want to use DTO rather than Entity in List that is easy just create Interface and replace it with DTO in List.
Example:
@Query(value = "select id, age, name FROM Person WHERE age=?1", nativeQuery=true)
List<PersonView> getPersonsByAge(int age);
and an interface
public interface PersonView {
Long getId();
Integer getAge();
String getName();
Well I have another answer I have used Interfaces for Projections and Classes for
Dto's and I am using ModelMapper to map my Projections to Dto Class
So my 1 Dto class may have many Projections which can mapped to Dto and used to Taste
gradle
implementation 'org.modelmapper:modelmapper:3.1.0'
@Autowired
private ModelMapper modelMapper;
List<UserDto> usersdto = repository.findUserByRoleName().stream().map(userprojection -> modelMapper.map(userprojection, UserDto.class))
.collect(Collectors.toList());
My projection is like this
public interface UserProjection {
String getId();
String getEmail();
My dto is
@Data
@AllArgsConstructor
@NoArgsConstructor
public class UserDto {
private long id;
private String firstName;
private String lastName;
private String phone;
private String email;
And I am able to get fields from custom queries
For example:
In your code, the repository where you placed you query extends JpaRepository that with class and id type <ABDeadlineType, Long>. So it expects to return ABDeadlineType data.
public interface DeadlineTypeRepository extends JpaRepository<ABDeadlineType, Long> {
List<DeadlineType> findAllSummarizedBy();
As you want to get DeadlineType data, you should keep your query in such repository like
public interface DeadlineTypeRepository extends JpaRepository<DeadlineType, Long>
So, either replace the class name inside JpaRepository<>
Or place your query in another repository. Then you don't need to do any mapping or write extra codes for it.
In my case, it worked.
For me projection solve this problem here is the code segments. this is the native query for this example
SELECT cifno,accnbr FROM institutedb.customerWHERE id = 100200
Step 1:
First Create a Entity class relevant to any table
@Entity
@Table(name = "customer", schema = "institutedb")
@Data
@NoArgsConstructor
@AllArgsConstructor
@Builder
public class CustomerEntity {
private int id;
private BigInteger accnbr;
private String actdate;
private int active;
Step2:
Then clean projection interface and DTO class. keep remind the interface getter method should have naming convention is DTO properties has got.
Projection Interface
public interface CustomerProjection {
String getCifno();
String getAccnbr();
DTO Class
@Data
@AllArgsConstructor
@NoArgsConstructor
@Builder
public class CustomerDTO {
private String cifno;
private String accnbr;
Step 3:
Next create the repository to embed the native query
public interface CustomerModelReporsitoy extends JpaRepository<CustomerEntity,String> {
@Query(
value = "SELECT cifno,accnbr FROM institutedb.customerWHERE id = 100200",
nativeQuery = true
List<CustomerProjection> findCifByUserName();
Step 4:
Create a get mapping for testing purpose and access the repo method
@GetMapping("/custmodel")
public String getCifModel(){
ModelMapper modelMapper = new ModelMapper();
List<CustomerProjection> collect = customerModelReporsitoy.findCifByUserName().stream().map(customerProjection -> modelMapper.map(customerProjection, CustomerProjection.class))
.collect(Collectors.toList());
collect.stream().forEach((cust)-> {
System.out.println(cust.getCifno());
System.out.println(cust.getAccnbr());
return "cif";
As a work around Solution for those who can not determine how the required object will be returned back
i used this way and it fits with native query
@Query(" what ever query " , nativeQuery = true)
List<Map<String, Object>> getAllExportData() ;
Thanks for contributing an answer to Stack Overflow!
- Please be sure to answer the question. Provide details and share your research!
But avoid …
- Asking for help, clarification, or responding to other answers.
- Making statements based on opinion; back them up with references or personal experience.
To learn more, see our tips on writing great answers.