这是关于调整和增强Spring Data MongoDB功能的第三篇文章。 这次,我发现我错过了一个JPA功能– @OrderBy批注。 @OrderBy指定在检索关联值时集合值关联的元素的顺序。

在本文中,我将展示如何使用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集合进行排序相关推荐

  1. orderby排序慢_使用@OrderBy对Spring Data MongoDB集合进行排序

    orderby排序慢 这是关于调整和增强Spring Data MongoDB功能的第三篇文章. 这次,我发现我错过了一个JPA功能– @OrderBy批注. @OrderBy指定在检索关联值时集合值 ...

  2. mongodb数据库java接口,MongoDB —— 使用Spring Data MongoDB操作数据库

    我们使用Spring Data MongoDB可以方便的在Spring boot项目中操作MongoDB 文档地址:https://docs.spring.io/spring-boot/docs/2. ...

  3. 使用Spring访问Mongodb的方法大全——Spring Data MongoDB查询指南

    1.概述 Spring Data MongoDB 是Spring框架访问mongodb的神器,借助它可以非常方便的读写mongo库.本文介绍使用Spring Data MongoDB来访问mongod ...

  4. Spring Data MongoDB教程

    在当今世界,尽快启动并运行应用程序非常重要. 该应用程序还应该易于开发和维护. Spring是这样的框架,它提供了与许多不同框架的集成的简便性,这使得使用Spring开发应用程序变得容易. 一种这样的 ...

  5. 数据聚合Spring Data MongoDB:嵌套结果

    1引言 在上一篇文章中,我们构建了聚合管道的基本示例. 如果您需要有关如何创建项目和配置应用程序的更多详细信息,也许您想看看使用Spring Data MongoDB和Spring Boot进行数据聚 ...

  6. 使用NoSQLUnit测试Spring Data MongoDB应用程序

    Spring Data MongoDB是Spring Data项目中的项目,它提供了Spring编程模型的扩展,用于编写使用MongoDB作为数据库的应用程序. 要使用NoSQLUnit为Spring ...

  7. Spring Data MongoDB示例

    Spring Data MongoDB示例 欢迎使用Spring Data MongoDB示例.Spring Data MongoDB是将Spring Framework与最广泛使用的NoSQL数据库 ...

  8. spring data mongodb CURD

    一.添加 Spring  Data  MongoDB 的MongoTemplate提供了两种存储文档方式,分别是save和insert方法,这两种的区别: (1)save :我们在新增文档时,如果有一 ...

  9. mongo java 注解,在Java中使用Spring Data MongoDB操作Mong | zifangsky的个人博客

    前言:在上一篇文章中(PS:https://www.zifangsky.cn/923.html)我简单介绍了如何在Linux中安装MongoDB以及MongoDB的增删改查等基本命令用法(PS:更多M ...

最新文章

  1. R语言可视化包ggplot2改变图例(legend)的标题(title)实战
  2. Java_Notes_基础排序总结与对比
  3. [云炬创业学笔记]第三章商业创意的发掘与评估测试5
  4. java 并发 同步信号_Java并发教程–信号量
  5. 本月风味– Neo4j和Heroku
  6. 单片机检测电机频率c语言,基于51单片机的电动机测速表的设计.doc
  7. Error解决:hive中的数组越界异常IndexOutOfBoundsException
  8. java循环1000000000_Java11比Java8快多少,不是测试人员一眼也能看懂
  9. linux 修改php配置,PHP部署时的几个配置修改说明
  10. CSS伪元素与伪类的区别
  11. MATLAB2016b 下载和安装(亲测)
  12. javaweb课程设计在线学习论坛
  13. 一家中国公司把城市变成了AI版《清明上河图》
  14. 小米电脑任务栏卡死点不动
  15. 二项分布期望和方差公式推导
  16. Whisper的应用
  17. Verilog设计流水灯(一)
  18. go install报错no install location for directory outside GOPATH
  19. HTML5开发 页游/手游动画及游戏系列教程(Game Tutorial):(一)物体动起来吧
  20. 【转载】HTML之图像的处理(六)

热门文章

  1. http响应状态码列表
  2. Spring IOC 如何解决循环依赖?
  3. corda_Corda服务的异步流调用
  4. java流写入数据库_Java 8:在2分钟内将智能流与数据库一起使用
  5. openshift_Openshift源中的高可用性Drools无状态服务
  6. java ee maven_真正释放Maven和Java EE的强大功能
  7. Spring Reactive已经过时了吗? 螺纹连接反转
  8. java集合根据值排序_Java 8:对集合中的值进行排序
  9. JDK Bug系统浪费时间
  10. java.util接口_函数接口– Java 8中java.util.function包中的函数接口