I've a custom query inside a jpa repository class:
package it.univaq.we.internshipTutor.repository;
import ...
public interface ProfessorRepository extends JpaRepository<Professor, Long> {
    List<Professor> findAll();
    ...
    @Query(value =  "SELECT professor.id, professor.department_id, " +
                    "professor.first_name, professor.last_name, " +
                    "professor.email, COUNT(professor_id) as count " +
                    "FROM professor LEFT JOIN student_internship ON professor.id = professor_id " +
                    "GROUP BY professor_id ORDER BY count DESC LIMIT ?1", nativeQuery = true)
    List<ProfessorInternshipCount> mostRequestedProfessors(int limit);
}
The query returns the 10 most requested internship tutors/professors; the result is composed by the information of the Professor and an integer value (the count).
Professor model class:
package it.univaq.we.internshipTutor.model;
import ...
@Entity
@Table(name = "professor")
public class Professor {
    @Id
    @GeneratedValue(strategy = GenerationType.IDENTITY)
    @Column(name = "id", nullable = false)
    private Long id;
    @Transient
    private UUID uuid;
    @ManyToOne(fetch = FetchType.LAZY)
    @JoinColumn(name = "department_id", nullable = false)
    @NotNull(message = "this field is mandatory")
    private Department department;
    @OneToMany(fetch = FetchType.LAZY, mappedBy = "professor")
    private List<StudentInternship> studentInternships;
    @Column(name = "first_name", nullable = false, length = 255)
    @NotEmpty
    private String firstName;
    @Column(name = "last_name", nullable = false, length = 255)
    @NotEmpty
    private String lastName;
    @Column(name = "email", nullable = false, length = 255)
    @Email
    @NotEmpty
    private String email;
    ...getters and setters...
}
ProfessorInternshipCount model (created to incapsulate the result of the query):
package it.univaq.we.internshipTutor.model;
public class ProfessorInternshipCount {
    private Professor professor;
    private Integer count;
    public ProfessorInternshipCount(Professor professor, int count) {
        this.professor = professor;
        this.count = count;
    }
    ...getters and setters...
}
Now, I've difficulties in binding what the query returns with the model I've created. More precisely I get the following exception:
org.springframework.core.convert.ConverterNotFoundException: 
    No converter found capable of converting from type 
    [org.springframework.data.jpa.repository.query.AbstractJpaQuery$TupleConverter$TupleBackedMap] 
    to type 
    [it.univaq.we.internshipTutor.model.ProfessorInternshipCount]
...
Am I doing something wrong? Is there a better way of doing what I'am trying to do?
You can easily achive this using projection. Here you have the bellow columns :
private String firstName;
private String lastName;
private Long id;
Create an Interface with getter from your query. Your projection will like this:
public interface ITestProjection {
    Long getId();
    Integer getCount();
    String getFirstName();
    String getLastName();
}
Your Query will like this :
@Query(value = "SELECT professor.id, professor.department_id, " +
                    "professor.first_name, professor.last_name, " +
                    "professor.email, COUNT(professor_id) as count " +
                    "FROM professor LEFT JOIN student_internship ON professor.id = professor_id " +
                    "GROUP BY professor_id ORDER BY count DESC LIMIT =?1", nativeQuery = true)
    ArrayList<ITestProjection> findDataWithCount(Integer limit);
Hope this will solve your problem.
For more details visit this thread.
Thanks :)
For example, let's that we have:
User - entity object with many fields.
UserBean - just object where our data will be converted.
Bad practice:
 @Repository
    public class ReportingRepository {
        @PersistenceContext
        private EntityManager em;
        public List<UserBean> findQuery() {
            Query query = em.createNativeQuery("select  ...  from Table  INNER JOIN ...");
            List<UserBean> items = (List<UserBean>) query.getResultList();
            return items;
        }
    }
but it will return values in arrays, so it will be more beautiful if we write the following code, that is better practice:
query.unwrap(SQLQuery.class)
           .addScalar("instance name", StringType.INSTANCE)
           .addScalar("second instance name", IntegerType.INSTANCE)
           .setResultTransformer(Transformers.aliasToBean(UserBean.class));
   List<UserBean> items = query.getResultList();
So finally everything is converted to UserBean class. Note that in addScalar method you should pass instance variable name (in your question you have count variable )
You can do this by either following ways.
Go through the article to get more detail.
http://javasampleapproach.com/spring-framework/spring-data/query-alter-domain-model-spring-jpa-projection-springboot-mysql-database
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