J'ai une requête personnalisée dans une classe de référentiel jpa:
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);
}
La requête renvoie les 10 tuteurs/professeurs de stage les plus demandés; le résultat est composé des informations du professeur et d'une valeur entière (le nombre).
Professeur classe modèle:
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...
}
Modèle ProfessorInternshipCount (créé pour incapsuler le résultat de la requête):
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...
}
Maintenant, j'ai du mal à lier ce que la requête retourne avec le modèle que j'ai créé. Plus précisément, je reçois l'exception suivante:
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]
...
Est-ce que je fais quelque chose de mal? Y a-t-il une meilleure façon de faire ce que j'essaie de faire?
Vous pouvez facilement y parvenir en utilisant la projection. Voici les colonnes ci-dessous:
private String firstName;
private String lastName;
private Long id;
Créez une interface avec getter à partir de votre requête. Votre projection aimera ceci:
public interface ITestProjection {
Long getId();
Integer getCount();
String getFirstName();
String getLastName();
}
Votre requête aimera ceci:
@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);
J'espère que cela résoudra votre problème.
Pour plus de détails, visitez ce fil .
Merci :)
Par exemple, disons que nous avons:
tilisateur - objet entité avec de nombreux champs.
serBean - juste un objet où nos données seront converties.
Mauvaise pratique:
@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;
}
}
mais il renverra des valeurs dans tableaux, donc ce sera plus beau si nous écrivons le code suivant, c'est-à-dire meilleure pratique:
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();
Donc, finalement, tout est converti en classe UserBean. Note que dans la méthode addScalar vous devez passer le nom de variable d'instance (dans votre question vous avez count variable)
Vous pouvez le faire de l'une des manières suivantes.
Parcourez l'article pour obtenir plus de détails.