orderby排序慢

这是关于调整和增强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排序慢

orderby排序慢_使用@OrderBy对Spring Data MongoDB集合进行排序相关推荐

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

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

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

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

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

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

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

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

  5. SpringBoot 集成 Spring Data Mongodb 操作 MongoDB 详解

    一.MongoDB 简介 MongoDB 是一个介于关系数据库和非关系数据库之间的产品,是非关系数据库当中功能最丰富,且与关系数据库的最为相像的.它支持的数据结构非常松散,是类似 json 的 bso ...

  6. Spring认证中国教育管理中心-Spring Data MongoDB教程五

    原标题:Spring认证中国教育管理中心-Spring Data MongoDB教程五(内容来源:Spring中国教育管理中心) 11.6.5.GeoJSON 支持 MongoDB 支持GeoJSON ...

  7. Spring Data MongoDB 学习和使用

    1.准备环境 新建一个Springboot项目 点击finish完成项目的搭建 2.配置连接参数 # application.properties # 配置数据库连接 #格式: mongodb://账 ...

  8. Spring Data MongoDB教程

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

  9. Spring Data MongoDB级联保存在DBRef对象上

    默认情况下, Spring Data MongoDB不支持对带有@DBRef注释的引用对象的级联操作,如引用所述 : 映射框架不处理级联保存 . 如果更改了Person对象引用的Account对象,则 ...

最新文章

  1. Oracle如何代码编辑,配置UltraEdit为Oracle PL/SQL代码编辑器
  2. Mysql Cluster节点类型
  3. mybatis foreach 错误_MyBatis高级结果映射之一对一映射
  4. JAVA8 Optional新特性和使用详解
  5. Java - 初识Java
  6. 初二模拟赛总结(2019.8.7)
  7. 【转】Magento2 数据库操作
  8. Java常用性能分析工具 jconsole、jvisualvm、 jstat、jinfo、jmap、jhat、jstack
  9. scala 隐式参数入门及应用
  10. 【洛谷P3369】【模板】普通平衡树题解
  11. java migration_JetPack知识点实战系列九:Room数据库Migration
  12. 2021 第四届安洵杯 MISC wp
  13. csv文件用什么打开_什么是CSV文件,如何打开它?
  14. Mac下Go的安装与配置
  15. 阿里云--短信服务---开通步骤
  16. 给view添加单边阴影
  17. Design a Facebook NewsFeed
  18. ros:init()
  19. ChinaSoft 论坛巡礼 | 软件工程教学案例交流与竞赛
  20. Mesos+Marathon搭建部署

热门文章

  1. Oracle入门(四)之查询基本信息
  2. 关于人脸和指纹识别共同交流方案
  3. C#基础知识详解之【字段与属性】
  4. 2020蓝桥杯省赛---java---B---2(寻找 2020)+测试txt
  5. SparkContext源码分析
  6. oracle8修改最大连接数,ORACLE查看并修改最大连接数的具体步骤
  7. org.springframework.amqp.AmqpConnectException java.net.ConnectException的解决办法
  8. 拦截第三方快递物流 ,console控制台打印正常 ,浏览器显示正常 ,传至后台乱码
  9. thinking-in-java(10)内部类
  10. jvm(8)-虚拟机字节码执行引擎