使用@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集合进行排序相关推荐
- orderby排序慢_使用@OrderBy对Spring Data MongoDB集合进行排序
orderby排序慢 这是关于调整和增强Spring Data MongoDB功能的第三篇文章. 这次,我发现我错过了一个JPA功能– @OrderBy批注. @OrderBy指定在检索关联值时集合值 ...
- mongodb数据库java接口,MongoDB —— 使用Spring Data MongoDB操作数据库
我们使用Spring Data MongoDB可以方便的在Spring boot项目中操作MongoDB 文档地址:https://docs.spring.io/spring-boot/docs/2. ...
- 使用Spring访问Mongodb的方法大全——Spring Data MongoDB查询指南
1.概述 Spring Data MongoDB 是Spring框架访问mongodb的神器,借助它可以非常方便的读写mongo库.本文介绍使用Spring Data MongoDB来访问mongod ...
- Spring Data MongoDB教程
在当今世界,尽快启动并运行应用程序非常重要. 该应用程序还应该易于开发和维护. Spring是这样的框架,它提供了与许多不同框架的集成的简便性,这使得使用Spring开发应用程序变得容易. 一种这样的 ...
- 数据聚合Spring Data MongoDB:嵌套结果
1引言 在上一篇文章中,我们构建了聚合管道的基本示例. 如果您需要有关如何创建项目和配置应用程序的更多详细信息,也许您想看看使用Spring Data MongoDB和Spring Boot进行数据聚 ...
- 使用NoSQLUnit测试Spring Data MongoDB应用程序
Spring Data MongoDB是Spring Data项目中的项目,它提供了Spring编程模型的扩展,用于编写使用MongoDB作为数据库的应用程序. 要使用NoSQLUnit为Spring ...
- Spring Data MongoDB示例
Spring Data MongoDB示例 欢迎使用Spring Data MongoDB示例.Spring Data MongoDB是将Spring Framework与最广泛使用的NoSQL数据库 ...
- spring data mongodb CURD
一.添加 Spring Data MongoDB 的MongoTemplate提供了两种存储文档方式,分别是save和insert方法,这两种的区别: (1)save :我们在新增文档时,如果有一 ...
- mongo java 注解,在Java中使用Spring Data MongoDB操作Mong | zifangsky的个人博客
前言:在上一篇文章中(PS:https://www.zifangsky.cn/923.html)我简单介绍了如何在Linux中安装MongoDB以及MongoDB的增删改查等基本命令用法(PS:更多M ...
最新文章
- R语言可视化包ggplot2改变图例(legend)的标题(title)实战
- Java_Notes_基础排序总结与对比
- [云炬创业学笔记]第三章商业创意的发掘与评估测试5
- java 并发 同步信号_Java并发教程–信号量
- 本月风味– Neo4j和Heroku
- 单片机检测电机频率c语言,基于51单片机的电动机测速表的设计.doc
- Error解决:hive中的数组越界异常IndexOutOfBoundsException
- java循环1000000000_Java11比Java8快多少,不是测试人员一眼也能看懂
- linux 修改php配置,PHP部署时的几个配置修改说明
- CSS伪元素与伪类的区别
- MATLAB2016b 下载和安装(亲测)
- javaweb课程设计在线学习论坛
- 一家中国公司把城市变成了AI版《清明上河图》
- 小米电脑任务栏卡死点不动
- 二项分布期望和方差公式推导
- Whisper的应用
- Verilog设计流水灯(一)
- go install报错no install location for directory outside GOPATH
- HTML5开发 页游/手游动画及游戏系列教程(Game Tutorial):(一)物体动起来吧
- 【转载】HTML之图像的处理(六)
热门文章
- http响应状态码列表
- Spring IOC 如何解决循环依赖?
- corda_Corda服务的异步流调用
- java流写入数据库_Java 8:在2分钟内将智能流与数据库一起使用
- openshift_Openshift源中的高可用性Drools无状态服务
- java ee maven_真正释放Maven和Java EE的强大功能
- Spring Reactive已经过时了吗? 螺纹连接反转
- java集合根据值排序_Java 8:对集合中的值进行排序
- JDK Bug系统浪费时间
- java.util接口_函数接口– Java 8中java.util.function包中的函数接口