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

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

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/news/372105.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

@SuppressLint(NewApi)和@TargetApi()的区别

转自&#xff1a;http://blog.csdn.NET/wbshuang09/article/details/44920549在Android代码中&#xff0c;我们有时会使用比我们在AndroidManifest中设置的android:minSdkVersion版本更高的方法&#xff0c;此时编译器会提示警告&#xff0c;解决方法是在方法上加上SuppressLin…

零基础自学编程前需要知道的知识

你是否适合编程?学习编程后能做什么?如何选择编程语言?有哪些免费的线上学习网站推荐?今天这篇好文将那些自学编程前需要了解和思考的问题都记录下来&#xff0c;希望能给那些刚刚开始或正准备自学编程的朋友们带去一些启发。 你是否适合自学编程 自学编程会是一个漫长而艰…

oracle系统库名,Oracle 札记之 一:数据库名,数据库实例名,数据库域名,操作系统环境变量...

数据库名是用于区分数据库的一个内部标识&#xff0c;是以二进制方式存储在数据库控制文件中的参数。数据库创建之后不能再修改这个参数。数据库创建后&#xff0c;它被写入数据库参数文件pfile或Spfile中。格式如下&#xff1a;...db_name"orcl"db_domaindbcenter.t…

用于基于SWT的应用程序的RichText编辑器组件

本文将完成使用SWT实现我们自己的RichText编辑器组件的任务。 在为我的一位客户开发基于桌面的应用程序时&#xff0c;我遇到了这样一个可视化组件的需求&#xff0c;并希望添加一项功能&#xff0c;以允许用户使用粗体&#xff0c;斜体&#xff0c;删除线等功能来写富文本注释…

Eclipse设置黑色主题

1点击help--->install new software 2输入 http://eclipse-color-theme.github.com/update 3下载安装eclipse color theme插件如下图 4完成后点击windows--->preferences------>Appearance下多了一个Color Theme 5,点击选择喜欢的主题即可&#xff0c;也可以自己下载主…

wcf rest系列文章

http://www.cnblogs.com/artech/archive/2012/02/15/wcf-rest.html 需要注意的是&#xff0c;发布的服务&#xff0c;可以在web behavior中指定显示help页面。 http://localhost/ApplicationName/ServiceName.svc/help 需要注意的是&#xff0c;访问.svc的页面一定不要多加/;否…

登录:应用程序错误通知

几个月前&#xff0c;当我进行大型应用程序重构时&#xff0c;发现用于记录日志的基于log4j的代码确实令人讨厌&#xff0c;重复了数百次&#xff1a; if (LOG.isDebugEnabled()) {LOG.debug("Logging some stuff " stuff); }我想摆脱isXXXEnabled&#xff0c;这就…

win10 oracle怎样卸载,Win10系统卸载Oracle 11g数据库的方法

说起Oracle 11g数据库编程人员没有一个不知道的&#xff0c;虽然它很好用&#xff0c;但是有时候我们也会想去卸载它&#xff0c;那么系统城win10纯净版怎么卸载Oracle 11g数据库呢&#xff1f;不知道的朋友赶紧看看小编整理的卸载Oracle 11g数据库的方法吧&#xff01;具体卸载…

.net 连接数据库

""符号是防止将后面字符串中的"\"解析为转义字符. using System.Data; using System.Data.SqlClient; ... string strConnection"user idsa;password;"; strConnection"initial catalogNorthwind;ServerYourSQLServer;"; st…

mysql DCL数据控制语言

-- 维护性操作 都是在cmd下操作的连接数据库&#xff1a; 本机&#xff1a;mysql [-h localhost] -u account -p 远程&#xff1a;mysql [-h remote_ip] -u account -p 显示当前所有数据库&#xff1a;show databases; 切换数据库&#xff1a;use db_name; …

如何分析线程转储–线程堆栈跟踪

本文是“ 线程转储”分析系列的第5部分。 到目前为止&#xff0c;您已经了解了线程的基本原理以及它们与Java EE容器和JVM的交互。 您还学习了HotSpot和IBM Java VM的不同线程转储格式。 现在是您深入分析过程的时候了。 为了使您能够从线程转储中快速识别问题模式&#xff0c;…

linux想要ping需要开启哪个端口,linux下iptales配置

linux iptables存放位置/etc/sysconfig/iptables[roottp ~]#iptables -I INPUT 5 -p tcp -m state --state NEW -m tcp --dport 1521 -j ACCEPT[roottp ~]#iptables -R INPUT 4 -s 172.17.99.0/24 -p tcp -m state --state NEW -m tcp --dport 22 -j ACCEPT[roottp ~]#iptables…

设计模式学习笔记(十三:原型模式)

1.1概述 用原型实例指定创建对象的种类&#xff0c;并且通过复制这些原型创建新的对象。这就是原型模式的定义。 在某些情况下&#xff0c;可能不希望反复使用类的构造方法创建许多对象&#xff0c;而是希望使用该类创建一个对象后&#xff0c;以该对象为原型得到该对象的若干个…

翻译的一篇关于学习编程语言的小文章

Top programming languages to get a job in Toronto in 2017 在程序开发人员和软件工程师中最容易被提及的问题之一就是&#xff1a;“我要学的下一门编程语言该是谁&#xff1f;” 我想去选一个编程语言&#xff0c;我希望你能给我一些关于经常使用到的编程语言的建议&#x…

从linux内核启动,学习Linux内核启动过程:从start_kernel到init

一、实验步骤&#xff1a;1&#xff1a;运行menuos&#xff1a;a)cd LinuxKernel/b)qemu -kernel linux-3.18.6/arch/x86/boot/bzImage -initrd rootfs.img启动后启动了MenuOS。2:使用gdb调试跟踪menuos内核启动和运行过程&#xff1b;a)qemu -kernel linux-3.18.6/arch/x86/bo…

【转】nginx的优缺点

原博文出自于&#xff1a;http://blog.csdn.net/a454211787/article/details/22494485 感谢! 1、nginx相对于apache优点&#xff1a; 轻量级同样起web 服务比apache占用更少内存及资源 抗并发nginx 处理请求异步非阻塞而apache 则阻塞型高并发下nginx 能保持低资源低消耗高…

与Maven 3,Failsafe和Cargo插件的集成测试

开箱即用&#xff0c;可以在Maven中进行单元测试。 因此&#xff0c;它也经常用于集成测试。 这样做的主要缺点是集成测试可能需要花费更多的时间来执行&#xff0c;并且因为没有人喜欢每次构建都要等待很长时间–使用-Dmaven.test.skiptrue标志可以跳过测试 为了执行与Maven的…

Spring入门第二十五课

使用具名参数 直接看代码&#xff1a; db.properties jdbc.userroot jdbc.passwordlogan123 jdbc.driverClasscom.mysql.jdbc.Driver jdbc.jdbcUrljdbc:mysql://localhost:3306/selective-courses-systemjdbc.initPoolSize5 jdbc.maxPoolSize10 applicationContext.xml <?x…

linux强制回收内存,Linu系统cache强制回收

LINUX的内存管理机制&#xff0c;一般情况下不需要特意去释放已经使用的cache。Cache机制的存在&#xff0c;使得Linux对磁盘的读写速度是有较大的好处的。 在 Linux 操作系统中&#xff0c;当应用程序需要读取文件中的数据时&#xff0c;操作系统先分配一些内存&#xff0c;将…

HDU 1412 {A} + {B}

Problem Description给你两个集合。要求{A} {B}.注:同一个集合中不会有两个同样的元素.Input每组输入数据分为三行,第一行有两个数字n,m(0<n,m<10000),分别表示集合A和集合B的元素个数.后两行分别表示集合A和集合B.每一个元素为不超出int范围的整数,每一个元素之间有一个…