javascript
使用@OrderBy对Spring Data MongoDB集合进行排序
在本文中,我將展示如何使用Spring Data MongoDB使用@OrderBy批注實現排序 。 ?
用例
對于那些以前沒有使用過JPA @OrderBy的人來說,這只是一個簡短的例子。 我們這里有兩個類和一對多關系:
package pl.maciejwalkowiak.springdata.mongodb.domain;import org.bson.types.ObjectId; import org.springframework.data.annotation.Id; import org.springframework.data.mongodb.core.mapping.Document;@Document public class Backpack {@Idprivate ObjectId id;private List<Item> items;... }public class Item {private String name;private int price;... }背包在這里是主要類別,其中包含嵌入式物品清單。 從數據庫中加載背包時,其項目將按接近插入順序的順序加載。 如果我們想更改它并按其字段之一訂購商品怎么辦? 我們需要自己實現排序,然后再次擴展AbstractMongoEventListener 。
排序詳細信息:介紹@OrderBy
與JPA相反,在這種情況下,排序不能在數據庫級別進行。 我們需要在應用程序端注意這一點–可以在兩個地方完成:
- 在將對象轉換成MongoDB數據結構之前–如果我們要確保在MongoDB集合中正確對對象進行排序
- 將對象從MongoDB數據結構轉換為Java對象之后–如果我們只想確保應用程序內部的List正確排序
為了指定應該在哪個位置進行排序,我創建了SortPhase枚舉:
public enum SortPhase {AFTER_CONVERT,BEFORE_CONVERT; }最后– @OrderBy批注將包含三個幾乎自我描述的屬性:
package pl.maciejwalkowiak.springdata.mongodb;import org.springframework.data.mongodb.core.query.Order;import java.lang.annotation.ElementType; import java.lang.annotation.Retention; import java.lang.annotation.RetentionPolicy; import java.lang.annotation.Target;@Retention(RetentionPolicy.RUNTIME) @Target({ ElementType.FIELD }) public @interface OrderBy {/*** Field name*/String value();Order order() default Order.ASCENDING;SortPhase[] phase() default SortPhase.AFTER_CONVERT; }實現SortingMongoEventListener
聲明式排序必須使用反射。 為了保持代碼可讀性,我使用了commons-beanutils,但可以不使用它而手動完成。 在項目中添加以下依賴項:
<dependency><groupId>commons-beanutils</groupId><artifactId>commons-beanutils</artifactId><version>1.8.3</version> </dependency><dependency><groupId>commons-collections</groupId><artifactId>commons-collections</artifactId><version>3.2.1</version> </dependency>最后一部分是SortingMongoEventListener實現:
package pl.maciejwalkowiak.springdata.mongodb;import com.mongodb.DBObject; import org.apache.commons.beanutils.BeanComparator; import org.springframework.data.mongodb.core.mapping.event.AbstractMongoEventListener; import org.springframework.data.mongodb.core.query.Order; import org.springframework.util.ClassUtils; import org.springframework.util.ReflectionUtils;import java.lang.reflect.Field; import java.util.Arrays; import java.util.Collections; import java.util.List;/*** MongoEventListener that intercepts object before its converted to BasicDBObject (before it is saved into MongoDB)* and after its loaded from MongoDB.** @author Maciej Walkowiak*/ public class SortingMongoEventListener extends AbstractMongoEventListener {@Overridepublic void onAfterConvert(DBObject dbo, final Object source) {ReflectionUtils.doWithFields(source.getClass(), new SortingFieldCallback(source, SortPhase.AFTER_CONVERT));}@Overridepublic void onBeforeConvert(Object source) {ReflectionUtils.doWithFields(source.getClass(), new SortingFieldCallback(source, SortPhase.BEFORE_CONVERT));}/*** Performs sorting with field if:* <ul>* <li>field is an instance of list</li>* <li>is annotated with OrderBy annotation</li>* <li>OrderBy annotation is set to run in same phase as SortingFieldCallback</li>* </ul>*/private static class SortingFieldCallback implements ReflectionUtils.FieldCallback {private Object source;private SortPhase phase;private SortingFieldCallback(Object source, SortPhase phase) {this.source = source;this.phase = phase;}public void doWith(Field field) throws IllegalArgumentException, IllegalAccessException {if (field.isAnnotationPresent(OrderBy.class)) {OrderBy orderBy = field.getAnnotation(OrderBy.class);if (Arrays.asList(orderBy.phase()).contains(phase)) {ReflectionUtils.makeAccessible(field);Object fieldValue = field.get(source);sort(fieldValue, orderBy);}}}private void sort(Object fieldValue, OrderBy orderBy) {if (ClassUtils.isAssignable(List.class, fieldValue.getClass())) {final List list = (List) fieldValue;if (orderBy.order() == Order.ASCENDING) {Collections.sort(list, new BeanComparator(orderBy.value()));} else {Collections.sort(list, new BeanComparator(orderBy.value(), Collections.reverseOrder()));}}}} }為了使用它,您只需要在應用程序上下文中將該類聲明為Spring Bean:
<bean class="pl.maciejwalkowiak.springdata.mongodb.SortingMongoEventListener" />例
現在是從這篇文章的開頭將創建的OrderBy注釋添加到Backpack類的時候了。 假設我們要按價格降序訂購商品:
@Document public class Backpack {@Idprivate ObjectId id;@OrderBy(value = "price", order = Order.DESCENDING)private List<Item> items;... }而已。 現在,每次加載背包對象時(無論它的findAll,findOne還是您的自定義方法都沒有關系),背包中的物品將被訂購。 ?
摘要
SortingMongoEventListener是Spring Data MongoDB事件系統功能強大的另一個示例。 歡迎您發表評論,如果您認為此功能可能是Spring Data MongoDB的一部分,請告訴我。
參考: Software Development Journey博客上的JCG合作伙伴 Maciej Walkowiak 使用@OrderBy對Spring Data MongoDB集合進行排序 。
翻譯自: https://www.javacodegeeks.com/2012/07/sorting-spring-data-mongodb-collections.html
總結
以上是生活随笔為你收集整理的使用@OrderBy对Spring Data MongoDB集合进行排序的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: 使用Hibernate 4,JPA和Ma
- 下一篇: 广东为什么叫岭南 广东叫岭南的原因分析