2012-05-29 25 views
22

聲明使用輸入參數的屬性作爲查詢參數的Spring數據JPA查詢的最簡單方法是什麼?具有參數屬性的Spring數據JPA查詢

例如,假設我有一個實體類:

public class Person { 
    @Id 
    private long id; 

    @Column 
    private String forename; 

    @Column 
    private String surname; 
} 

和其他類:

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

    [constructor and getters] 
} 

...然後我想如下寫一個Spring數據倉庫:

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

...但是Spring數據/ JPA不喜歡指定上的屬性名稱參數。

什麼是最好的選擇? }

+0

它必須是動態的嗎?爲什麼你不能在from語句之後添加'Name'表? –

+0

'姓名'不一定是一個實體。 – Kkkev

回答

46

此鏈接將幫助您:春季數據JPA M1與支持規劃環境地政司表達式。類似的例子是:

@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

這是spring-data-jpa 1.7.2 +並且需要彈簧4 – chrismarx

+0

客戶似乎必須是一個實體,評估POJO對我來說不起作用。 – Schaka

+0

還沒有嘗試過pojo,我可以證實這是至少與實體合作。其他人也提到,如果他們包含對象和其他參數(請參閱此處的評論),他們會遇到問題 - https://spring.io/blog/2014/07/15/spel-support-in-spring- data-jpa-query-definitions – chrismarx

10

你想要什麼是不可能的。您必須創建兩個參數,並將它們分別綁定:

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

據推測,這需要在自定義存儲庫方法中實現,如http://static.springsource.org/spring-data/data-jpa/docs/current/reference/html/#repositories.single-repository-behaviour? – Kkkev

+1

我知道JPA是如何工作的,但我不知道彈簧數據會爲您做什麼,以及您必須自己做什麼。抱歉。 –

16

定義具有簽名的查詢方法,如下所示。

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

欲知詳情,請查看the Spring Data JPA reference

+1

這並沒有回答這個問題。相關的一點是,我想使用輸入參數的屬性作爲查詢參數,而不是單獨的輸入參數。 – Kkkev

+0

糟糕,我錯讀了您的查詢。 我相信Spring Data JPA不提供支持(可能甚至JDBC可能不會;我可能在這裏是錯誤的)。 作爲另一種選擇(除了自定義存儲庫方法),您可以編寫一個服務包裝方法,將Person對象作爲參數並將相關參數傳遞給存儲庫方法。這種方法的優點是,您期望的簽名(傳遞Person對象)完好無損,您還可以使用Spring Data JPA提供的實現。 –

5

你可以嘗試這樣的事情:

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

名稱不是實體,所以這不起作用。 – Kkkev

+0

@Kkkev多數民衆贊成在正確的,你需要使這個解決方案的名稱實體 – Casi

1

你有@Service過工作?因爲如果你是,那麼你可以@AutowiredPersonRepository@Service,然後在服務只是調用Name類和使用@CuriosMind形式...建議:

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

,並從調用方法時然後可以傳遞這些參數。

-1

如果我們使用JpaRepository,那麼它將在內部創建查詢。

樣品

findByLastnameAndFirstname(字符串姓氏,字符串姓名)

findByLastnameOrFirstname(字符串姓氏,字符串姓名)

findByStartDateBetween(日期DATE1,日期2)

findById( int id)

注意

如果假設我們需要複雜的查詢,那麼我們就需要編寫手動查詢,如

@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

你也可以用一個接口默認的方法解決這個問題:

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

當然,你仍然有公開的實際存儲庫功能isible ...