2012-05-29 13 views
22

Qual è il modo più semplice di dichiarare una query JPA di dati Spring che utilizza le proprietà di un parametro di input come parametri di query?Query JPA dati di primavera con proprietà parametro

Per esempio, supponiamo di avere una classe di entità:

public class Person { 
    @Id 
    private long id; 

    @Column 
    private String forename; 

    @Column 
    private String surname; 
} 

e un'altra classe:

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

    [constructor and getters] 
} 

... poi vorrei scrivere un repository di dati molla come segue:

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); 
} 

... ma i dati Spring/JPA non mi piacciono se si specificano i nomi delle proprietà su ?1 parametro.

Qual è l'alternativa più accurata? }

+0

Deve essere dinamico? Perché non puoi semplicemente aggiungere la tabella 'Name' dopo l'istruzione from? –

+0

'Nome' non è necessariamente un'entità. – Kkkev

risposta

46

Questo link vi aiuterà a: Primavera dati JPA M1 con le espressioni SPEL supportati. L'esempio simile potrebbe essere:

@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

+0

questo è spring-data-jpa 1.7.2 + e richiede la primavera 4 – chrismarx

+0

Il cliente sembra essere un'entità qui, la valutazione dei POJO non funziona per me. – Schaka

+0

Non ho provato con un pojo, posso confermare che funziona almeno con le entità. Qualcun altro ha menzionato il fatto che si sono imbattuti in problemi se includono sia un oggetto che argomenti aggiuntivi (vedere i commenti qui) - https://spring.io/blog/2014/07/15/spel-support-in-spring- data-jpa-query-definizioni – chrismarx

10

Quello che vuoi non è possibile. È necessario creare due parametri e collegarli separatamente:

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

Presumibilmente questo dovrebbe essere implementato in un metodo di repository personalizzato come da http://static.springsource.org/spring-data/data-jpa/docs/current/reference/html/#repositories.single-repository-behaviour? – Kkkev

+1

So come funziona JPA, ma non so cosa facciano i dati primari per te e cosa devi fare da solo. Scusate. –

16

Definire il metodo di query con le firme come segue.

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

Per ulteriori informazioni, controllare the Spring Data JPA reference

+1

Questo non risponde alla domanda. Il punto pertinente è che vorrei utilizzare le proprietà di un parametro di input come parametri di query, non parametri di input separati. – Kkkev

+0

Oops, ho letto male la tua domanda. Credo che il supporto non sia fornito da Spring Data JPA (probabilmente anche JDBC potrebbe non esserlo, potrei sbagliarmi qui). Come alternativa (a parte l'approccio del repository personalizzato), è possibile scrivere un metodo wrapper del servizio che accetta l'oggetto Person come parametro e passa i parametri rilevanti al metodo repository. Vantaggio con questo approccio è che la firma che ci si aspettava (passare oggetto Persona) è intatta e si utilizza anche l'implementazione fornita da Spring Data JPA. –

5

Si può provare qualcosa di simile:

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); 
    } 
+1

Il nome non è un'entità, quindi non funziona. – Kkkev

+0

@Kkkev va bene, è necessario rendere Nome un'entità per questa soluzione – Casi

1

Stai lavorando con un @Service troppo? Perché se si, allora si può @Autowired vostra PersonRepository al @Service e poi al servizio basta richiamare la classe Name e utilizzare il modulo che @CuriosMind ... proposto:

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

e quando si richiama il metodo dal repository nel servizio, è quindi possibile passare quei parametri.

-1

se si utilizza JpaRepository, verranno create internamente le query.

Esempio

findByLastnameAndFirstname (String cognome, String cognome)

findByLastnameOrFirstname (String cognome, String cognome)

findByStartDateBetween (Data date1, Data2)

findById (int id)

Nota

se supponiamo che abbiamo bisogno di query complesse allora abbiamo bisogno di scrivere query manuali come

@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); 
-2
@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(); 
    } 
0

Si potrebbe anche risolvere con un metodo di interfaccia di default:

@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()); 
} 

Ovviamente avresti ancora la funzione di repository effettiva v isible ...

Problemi correlati