Spring Data MongoDB (二) 查詢
創(chuàng)建查詢(去重、區(qū)間、忽略大小寫等)
查詢的構(gòu)建機(jī)制,將截斷前綴 find...By、 read...By、 query...By、 count...By、 get...By 等,從剩余部分開始解析,省略號中可以使用如:Distinct、Between、LessThan、GreaterThan、Like等表達(dá)式
interface PersonRepository extends Repository<User, Long> {
List<Person> findByEmailAddressAndLastname(EmailAddress emailAddress, String lastname);
// 使用 Distinct 去重
List<Person> findDistinctPeopleByLastnameOrFirstname(String lastname, String firstname);
List<Person> findPeopleDistinctByLastnameOrFirstname(String lastname, String firstname);
// 使用 IgnoreCase 忽略大小寫查詢
List<Person> findByLastnameIgnoreCase(String lastname);
// 使用 AllIgnoreCase 全部忽略大小寫
List<Person> findByLastnameAndFirstnameAllIgnoreCase(String lastname, String firstname);
// 使用 OrderBy (Field) ASC/DESC 進(jìn)行排序
List<Person> findByLastnameOrderByFirstnameAsc(String lastname);
List<Person> findByLastnameOrderByFirstnameDesc(String lastname);
}
屬性表達(dá)式(子屬性查詢)
即一個被管理實體的屬性,在查詢時,會去查找該屬性類的嵌套屬性類。如:Person 有一個 Health 屬性類,二Health 也有一個 HeartIm 屬性類,則通過方法名查詢?yōu)椋?/p>
List<Person> findByHealthHeartIm(HeartIm heartIm); // 相當(dāng)于 {health.heart:?0}
其查詢順序為,先匹配 healthheartIm 屬性是否存在,若否,匹配 healthHeart.Im ,最后才是 health.Heart.Im。再沒有則接著向下拆分。為了解決模糊不清的含義,我們可以在方法名中使用 “_” 手動創(chuàng)建分割點。
List<Person> findByHealth_HeartIm(HeartIm heartIm);
特殊參數(shù)(分頁、排序)
除了在查詢中定義處理方法參數(shù)之外,還有一些特殊的類型,如:Pageable 和 Sort,用于分頁和排序:
// Page 接口中返回了元素的總數(shù)、可分頁數(shù)等,其實是通過底層觸發(fā) count 方法進(jìn)行了總數(shù)查詢
Page<User> findByLastname(String lastname, Pageable pageable);
// Slice 僅僅知道是否有下一個可用的 Slice,在遍歷大結(jié)果集時非常有效
Slice<User> findByLastname(String lastname, Pageable pageable);
List<User> findByLastname(String lastname, Sort sort);
List<User> findByLastname(String lastname, Pageable pageable);
限制查詢結(jié)果(Top、First等)
查詢方法的結(jié)果可以通過關(guān)鍵字:first、top 來限制,緊跟隨的數(shù)值會限定長度,默認(rèn)為1
User findFirstByOrderByLastnameAsc();
User findTopByOrderByAgeDesc();
Page<User> queryFirst10ByLastname(String lastname, Pageable pageable);
Slice<User> findTop3ByLastname(String lastname, Pageable pageable);
List<User> findFirst10ByLastname(String lastname, Sort sort);
List<User> findTop10ByLastname(String lastname, Pageable pageable);
查詢結(jié)果流(Stream)
查詢的結(jié)果可以使用 java8 的 Stream<T> 來處理,這樣可以使用 stream 的良好性能。
@Query("select u from User u")
Stream<User> findAllByCustomQueryAndStream();
Stream<User> readAllByFirstnameNotNull();
@Query("select u from User u")
Stream<User> streamAllPaged(Pageable pageable);
因為 Stream 使用了底層的資源,所以在使用之后必須關(guān)閉:
try (Stream<User> stream = repository.findAllByCustomQueryAndStream()) {
stream.forEach(…);
}
而且,并不是所有的 Spring Data 模塊都支持 Stream
異步查詢結(jié)果
Repository 的查詢方法可以異步執(zhí)行,這意味著該方法在調(diào)用時會立即返回,但是 實際的查詢要提交給 Spring 的任務(wù)TaskExecutor
/** Future 的常用方法:
isCancelled():boolean
isDone():boolean
get():V
get(long timeout,@NotNull TimeUnit unit):V
*/
@Async
Future<User> findByFirstname(String firstname); // java.util.concurrent.Future
@Async
CompletableFuture<User> findOneByFirstname(String firstname); // Java 8 的 java.util.concurrent.CompletableFuture
@Async
ListenableFuture<User> findOneByLastname(String lastname); // org.springframework.util.concurrent.ListenableFuture
生成 Repository 實例
使用 xml 配置的方式 指定repositories 掃描的包路徑:
<repositories base-package="com.acme.repositories" />
使用注解的方式:
@Configuration
@EnableJpaRepositories("com.acme.repositories")
class ApplicationConfiguration {
@Bean
EntityManagerFactory entityManagerFactory() { // … }
}
以上是 Spring Data 的公共基礎(chǔ)部分,再往下就是 MongoDBFactory 等的底層實現(xiàn)了。才疏學(xué)淺,看不下去啊。就到這里吧,第八章。