100 votes

Requête Spring data JPA avec propriétés des paramètres

Quelle est la manière la plus simple de déclarer une requête Spring data JPA qui utilise les propriétés d'un paramètre d'entrée comme paramètres de la requête ?

Par exemple, supposons que j'ai une classe d'entité :

public class Person {
    @Id
    private long id;

    @Column
    private String forename;

    @Column
    private String surname;
}

et une autre classe :

public class Name {
    private String forename;
    private String surname;

    [constructor and getters]
}

... alors je voudrais écrire un référentiel de données Spring comme suit :

public interface PersonRepository extends CrudRepository<Person, Long> {
    @Query("select p from Person p where p.forename = ?1.forename and p.surname = ?1.surname")
    findByName(Name name);
}

... mais Spring data / JPA n'aime pas que je spécifie des noms de propriétés sur le fichier ?1 paramètre.

Quelle est la meilleure alternative ?

207voto

sunday Points 1873

Ce lien vous aidera : Spring Data JPA M1 avec support des expressions SpEL. Un exemple similaire serait :

@Query("select u from User u where u.firstname = :#{#customer.firstname}")
List<User> findUsersByCustomersFirstname(@Param("customer") Customer customer);

https://spring.io/blog/2014/07/15/spel-support-in-spring-data-jpa-query-definitions

24voto

CuriosMind... Points 351

Définissez la méthode d'interrogation avec les signatures comme suit.

@Query(select p from Person p where p.forename = :forename and p.surname = :surname)
User findByForenameAndSurname(@Param("surname") String lastname,
                             @Param("forename") String firstname);
}

Pour plus de détails, consultez la référence Spring Data JPA

10voto

JB Nizet Points 250258

Ce que vous voulez n'est pas possible. Vous devez créer deux paramètres, et les lier séparément :

select p from Person p where p.forename = :forename and p.surname = :surname
...
query.setParameter("forename", name.getForename());
query.setParameter("surname", name.getSurname());

9voto

mmey Points 1171

Vous pourriez également résoudre ce problème avec une méthode par défaut de l'interface :

 @Query(select p from Person p where p.forename = :forename and p.surname = :surname)
User findByForenameAndSurname(@Param("surname") String lastname,
                         @Param("forename") String firstname);

default User findByName(Name name) {
  return findByForenameAndSurname(name.getLastname(), name.getFirstname());
}

Bien sûr, vous auriez toujours la fonction de dépôt réelle visible publiquement...

8voto

Casi Points 81

Vous pouvez essayer quelque chose comme ça :

public interface PersonRepository extends CrudRepository<Person, Long> {
       @Query("select p from Person AS p"
       + " ,Name AS n"  
       + " where p.forename = n.forename "
       + " and p.surname = n.surname"
       + " and n = :name")
       Set<Person>findByName(@Param("name") Name name);
    }

Prograide.com

Prograide est une communauté de développeurs qui cherche à élargir la connaissance de la programmation au-delà de l'anglais.
Pour cela nous avons les plus grands doutes résolus en français et vous pouvez aussi poser vos propres questions ou résoudre celles des autres.

Powered by:

X