2016-01-25 42 views
1

我一直在學習春天引導框架近日,據我的研究,我可以帶有ORM,EntityManager,@Query的Spring Data Repository,處理自定義SQL查詢的最優雅的方法是什麼?

  • 包括在Maven的依賴列表Hibernate的JPA實現,擴展CrudRepository並添加自定義方法

  • 使用EntityManager從Hibernate來執行自定義的SQL查詢

  • 使用註釋@org.springframework.data.jpa.repository.Query

問題

  • 他們是否緩存我查詢的數據?

  • 它們是否具有相同的性能?

  • 哪一個是最適合自定義SQL查詢的方法?如果它們都不是,那麼在使用Spring框架(不限於存儲庫模式)和Hibernate時,是否有其他方式來處理自定義SQL查詢?

1.存儲庫的方法

@Entity 
@Table(name = Collection.TABLE_NAME) 
public class Collection { 
    public final static String TABLE_NAME = "collection"; 
    ... 
} 

public interface CollectionRepository extends CrudRepository<Collection, Integer> { 
} 

public class CollectionRepositoryImpl { 
    @Autowired 
    private CollectionRepository collectionRepository; 

    public List<Collection> findCollectionsForSeason(int season, int count) { 
     List<Collection> results = new ArrayList<>(); 

     for (Collection c : collectionRepository.findAll()) { 
      if (c.getSeason() == season) { 
       results.add(c); 
      } 
     } 

     return results; 
    } 
} 

2. EntityManager的方法

public class xxx { 
    private EntityManager em; 
    ... 

    public List<Collection> findCollectionsForSeason(int season, int count) { 
     String sqlString = String.format("SELECT * FROM `collection` WHERE `season`=%d LIMIT %d", season, count); 
     return this.em.createNativeQuery(sqlString).getResultList(); 
    } 
} 

3. @Query方法

注意:下面的這段代碼是錯誤的,但我無法弄清楚如何正確地做到這一點。所以如果有人可以幫助我使用命名參數和限制子句(mysql)實現本機查詢,那將會很好。

public interface CollectionRepository extends CrudRepository<Collection, Integer> { 
    @Query(value = "SELECT * FROM `collection` WHERE `season`=%d LIMIT %d", nativeQuery = true) 
    List<Collection> findCollectionsForSeason(int season, int count) { 
    } 
} 

謝謝!

回答

1
  1. 您可以使用上述每種方法來緩存數據。因爲這是另一回事。您需要使用例如Ehcache或Redis,並在您想要緩存的方法上提供@Cacheable註釋。

  2. 非常相似,只要確保你不會搞砸了。我寧願使用JPARepository和原生查詢,但這是個人喜好的問題。您可以查看幾篇文章,例如:http://wiki.aiwsolutions.net/2014/03/18/spring-data-versus-traditional-jpa-implementation/

  3. 對於此:@Query(value = "SELECT * FROM collection WHERE season=%d LIMIT %d", nativeQuery = true),您可以創建JPARepository方法而不是本地查詢。類似的東西:

    findBySeason(Object season, Pageable pageable);

    在這裏閱讀更多: http://docs.spring.io/spring-data/jpa/docs/1.4.3.RELEASE/reference/html/jpa.repositories.html

1

所有三種方式使用墊層Hibernate實現執行本地查詢和搶的結果(在你第一次實現你'重新檢索每一個實體,所以它的性能會更差)。請記住,您可能將所有這些內容混合到一個存儲庫實現中,無需爲一個存儲庫遵循相同的模式。

就個人而言,我傾向於使用你的第三個辦法,這在我看來是最乾淨的方式,因爲它讓我們春季處理查詢,而不涉及實體管理器需要你的代碼。

public interface CollectionRepository extends CrudRepository<Collection, Integer> { 
    @Query(value = "SELECT * FROM collection WHERE season=:season LIMIT :count", nativeQuery = true) 
    List<Collection> findCollectionsForSeason(@Param("season") int season, @Param("count") int count); 
} 

實施結果正在返回的列,如果你把它們轉換成實體,必須在名字映射匹配機查詢時,只要記住。

每當你需要實現它將會在運行時處理更復雜的查詢,請記住,你將能夠提供擴展接口給出你自己的倉庫實現。

1

不要做任何這些事情。而不是擴展CrudRepository擴展PagingAndSortingRepository或(如您使用JPA)JpaRepository。如何使用以及如何限制結果在the reference guide中有解釋。

public interface CollectionRepository extends PagingAndSortingRepository <Collection, Integer> {} 

然後添加一個查找器方法,該方法需要您的參數和一個Pageable參數。

List<Collection> findByReason(String reason, Pageable page); 

現在,在你的服務,你可以這樣做

return collectionRepository.findByReason(reason, new PageRequest(0, count)); 

如果您需要爲您的查詢更多的靈活性,你可以隨時與Specification結合分頁方法。

public interface CollectionRepository 
    extends CrudRepository<Collection, Integer>, 
      JpaSpecificationExecutor<Collection> {} 

然後在你的服務

return collectionRepository.findAll(new YourSpecification(), new PageRequest(0, count)); 

,允許非常靈活的查詢生成(我們使用一般的實現,可我們大多數的搜索數據表)。

基本上它歸結爲與框架的工作(和理解它),而不是圍繞它的工作。

相關問題