Requête JPA Spring data avec Propriétés de paramètre

Quel est le moyen le plus simple de déclarer une requête JPA Spring data qui utilise les propriétés d'un paramètre d'entrée comme paramètres de 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]
}

... ensuite, 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 paramètre ?1.

Quelle est l'alternative la plus soignée? }

32
demandé sur Kkkev 2012-05-29 20:07:37

9 réponses

Ce lien vous aidera: Spring Data JPA M1 avec des expressions Spel prises en charge. L'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

62
répondu sunday 2015-03-11 17:48:30

Définissez la méthode de requête 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 JPA des données de printemps

18
répondu CuriosMind... 2014-06-02 05:42:38

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());
10
répondu JB Nizet 2012-05-29 17:14:45

, Vous pouvez essayer quelque chose comme ceci:

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);
    }
6
répondu Casi 2017-12-04 12:02:21

Travaillez-vous aussi avec un @Service? Parce que si vous l'êtes, alors vous pouvez @Autowired Votre {[3] } à la {[1] } et puis dans le service appelez simplement la classe Name et utilisez le formulaire que @ CuriosMind... proposé:

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

Et lorsque vous appelez la méthode à partir du référentiel dans le service, vous pouvez ensuite passer ces paramètres.

1
répondu Leo 2016-05-10 20:30:11

Vous pouvez également le résoudre 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 référentiel réelle visible publiquement...

1
répondu mmey 2017-12-22 11:47:22

Si nous utilisons JpaRepository, les requêtes seront créées en interne.

Exemple de

FindByLastnameAndFirstname(String nom,String prenom)

FindByLastnameOrFirstname(String nom,String prenom)

FindByStartDateBetween(Date date1, Date2)

FindById (int id)

Note

Si supposons que nous ayons besoin de requêtes complexes, nous devons écrire des requêtes manuelles comme

@Query("SELECT salesOrder FROM SalesOrder salesOrder WHERE salesOrder.clientId=:clientId AND salesOrder.driver_username=:driver_username AND salesOrder.date>=:fdate AND salesOrder.date<=:tdate ")
 @Transactional(readOnly=true)
 List<SalesOrder> findAllSalesByDriver(@Param("clientId")Integer clientId, @Param("driver_username")String driver_username, @Param("fdate") Date fDate, @Param("tdate") Date tdate);
-1
répondu Mohammad 2017-09-25 08:55:38
@Autowired
private EntityManager entityManager;

@RequestMapping("/authors/{fname}/{lname}")
    public List actionAutherMulti(@PathVariable("fname") String fname, @PathVariable("lname") String lname) {
        return entityManager.createQuery("select A from Auther A WHERE A.firstName = ?1 AND A.lastName=?2")
                .setParameter(1, fname)
                .setParameter(2, lname)
                .getResultList();
    }
-2
répondu Ram Pukar 2017-11-04 09:40:35
    for using this, you can create a Repository for example this one:
    Member findByEmail(String email);

    List<Member> findByDate(Date date);
    // custom query example and return a member
   @Query("select m from Member m where m.username = :username and m.password=:password")
        Member findByUsernameAndPassword(@Param("username") String username, @Param("password") String password);
-2
répondu KIBOU Hassan 2018-05-20 22:03:03