Java使用反射,把对象转换成 MongoDb 的结构

java基础教程栏目介绍如何把对象转换成MongoDb的结构

Java使用反射,把对象转换成 MongoDb 的结构

推荐(免费):java基础教程

反射是 Java 的一个高级技巧,大量地用在各种开源项目上。比如,Spring、Tomcat、Jetty 等等项目中,都大量地用到了反射。

作为 Java 程序员,我们如果用好反射,不但能提高自己的技术水平,还能开发出更好的项目。

然而,虽然很多人听说过反射,但却不知道应该用在哪里。

立即学习“Java免费学习笔记(深入)”;

那么,我们就从实际工作出发,使用反射,把对象转换成 MongoDb 的数据结构。当你在搞懂这个例子后,就能明白反射是怎么个用法。

需求分析

在电商系统中,一些数据要保存到 MongoDb 中,以此来提高查询的性能。但在此之前,我们必须把数据先转换成 MongoDb 的结构,也就是把 Java 对象转换成 Document。

比如,订单信息要存到 MongoDb 中,就得把订单对象转换成 Document。

可这样一来,每个实体类都得开发一个 2Doc() 方法。这个方法毫无技术含量,就是把各种字段 put 到 Document 里面。而且一旦字段多了,一不留神就会写错代码,你感受一下。

public class Order {    private Long id;    private Long userId;    private String orderNo;    private BigDecimal amount;    private String createTime;    private String updateTime;    // 省略无数字段        // 转换方法:订单转doc    public Document order2Doc(Order order) {        Document doc = new Document();        doc.put("id", order.getId());        doc.put("userId", order.getUserId());        doc.put("orderNo", order.getOrderNo());        doc.put("amount", order.getAmount());        doc.put("createTime", order.getCreateTime());        doc.put("updateTime", order.getUpdateTime());        // 省略无数put...        return doc;    }}

登录后复制

除此之外,我们还得从 MongoDb 中取数据,把 Document 转换回 Java 对象,你再感受一下。

public class Order {    private Long id;    private Long userId;    private String orderNo;    private BigDecimal amount;    private String createTime;    private String updateTime;    // 省略无数字段        // 转换方法:doc转订单    public Order doc2Order(Document doc) {        Order order = new Order();                order.setId((Long) doc.get("id"));        order.setUserId((Long) doc.get("userId"));        order.setOrderNo((String) doc.get("orderNo"));        order.setAmount((BigDecimal) doc.get("amount"));        order.setCreateTime((String) doc.get("createTime"));        order.setUpdateTime((String) doc.get("updateTime"));        // 省略无数set...        return order;    }}

登录后复制

光是一个订单类都这么麻烦了,何况这样的类不止一个,而且项目总有新需求,如果一个字段改了,那你麻烦大了,说不定要把整个项目翻一遍。

因此,为了少出错,必须优化这两个转换方法,而这次优化用到了 Java 的两个高级特性:反射、泛型。为了让大家更直观的了解,我将分成两个版本迭代。

第一版,利用反射,简化实体类的转换方法;第二版,利用泛型、反射,提取 MongoDb 工具类;

接下来,我们就一步步迭代吧~

利用反射,简化实体类的转换方法

在第一版的迭代中,我们要简化实体类的两个转换方法。

我们先从 Java 对象转 Document 开始,还是以 Order 类为例。

首先,我们通过反射,获取到订单类的所有字段信息;然后,使用循环遍历这些字段;最后,在循环中,我们放开字段的访问权限,把字段 put 到 Document 里面。

public class Order {    // ...省略无数字段    public Document order2Doc(Order order) throws Exception {        Document doc = new Document();        // 获取所有字段:通过 getClass() 方法获取 Class 对象,然后获取这个类所有字段        Field[] fields = order.getClass().getDeclaredFields();        for (Field field : fields) {            // 开放字段操作权限            field.setAccessible(true);            // 设置值            doc.put(field.getName(), field.get(order));        }        return doc;    }}

登录后复制

你可以看到,经过反射改造后,代码简单了很多。一个对象无论有多少个字段,要写多少 put 操作,只要这几行代码就能搞定。Java 对象转成 MongoDb 的结构,看起来也不那么麻烦了。

照着这个思路,我们再来改造第二个方法,Document 转 Java 对象。

public class Order {    // ...省略无数字段    public Order doc2Order(Document doc) throws Exception {        Order order = new Order();        for (String key : doc.keySet()) {            // 获取字段            Field field = order.getClass().getDeclaredField(key);            // 开放字段操作权限            field.setAccessible(true);            // 设置值            field.set(order, doc.get(key));        }        return order;    }}

登录后复制

首先,我们使用循环遍历 Document;在循环中,使用反射获取相应的字段,再放开字段的访问权限,把 Document 的值设置到对象的字段里。

到了这儿,我们利用反射,简化了两个实体类的转换方法,第一版的迭代基本完成了。剩下的工作,就是复制粘贴,把各个类重新改造一遍。

然而,经过这一版迭代,虽然减少了很多工作,但依然有很多不合理的地方。

首先,重复代码还是很多。每个实体类都有两个转换方法,但这两个方法的核心逻辑是一样的,完全没必要到处复制。

然后,这不是实体类应该承担的功能。实体类只负责短暂保留数据,不负责任何持久化功能。你把数据存到哪里,该转换成什么数据结构,这和实体类没什么关系。

换句话说,我们还得做第二次迭代。

利用泛型、反射,提取 MongoDb 工具类

简单来说,泛型是一种风格或范式,你不用一开始就指明具体的参数类型,而是在使用的时候再确定参数类型。

如果把泛型、反射结合在一起,能帮我们减少很多重复代码。

我们来看看,该怎么做第二次迭代?

先从 Java 对象转 Document 开始。我们先声明一个泛型方法;然后,通过反射,获取泛型类的所有字段信息,再使用循环遍历这些字段;最后,在循环中,把字段 put 到 Document 里面。

public class MongoDbUtils {    // 定义泛型方法:    // 1. 在返回值前,声明泛型参数 ;    // 2. 传入参数时,指定一个泛型参数    public static  Document obj2Doc(T obj) throws Exception {        Document doc = new Document();        // 获取所有字段:通过 getClass() 方法获取 Class 对象,然后获取这个类所有字段        Field[] fields = obj.getClass().getDeclaredFields();        for (Field field : fields) {            // 开放字段操作权限            field.setAccessible(true);            // 设置值            doc.put(field.getName(), field.get(obj));        }        return doc;    }}

登录后复制

在加入泛型后,重复代码大量减少了,实体类不用再单独写 2Doc()方法了。在使用的时候,只要调用 MongoDbUtils.obj2Doc() 就行。

按照同样的思路,我们继续来改造第二个方法,Document 转 Java 对象。

public class MongoDbUtils {    // 定义泛型方法:    // 1. 在返回值前,声明泛型参数 ;    // 2. 传入参数必须是 Class,但这个 Class 是泛型参数,不限制类型    public static  T doc2Obj(Document doc, Class clazz) throws Exception {        // 实例化泛型对象        T obj = clazz.newInstance();        for (String key : doc.keySet()) {            // 获取字段            Field field = clazz.getDeclaredField(key);            // 开放字段操作权限            field.setAccessible(true);            // 设置值            field.set(obj, doc.get(key));        }        return obj;    }}

登录后复制

首先,我们定义实例化一个泛型对象;然后,我们使用循环遍历 Document;最后,在循环中,使用反射获取相应的字段,把 Document 的值设置到泛型对象的字段里。

第二版的迭代就基本完成了。我们在第一版迭代的基础上,加入了泛型,得到了一个工具类 MongoDbUtils,这个工具类得到结果和以前完全一样,你可以看下测试代码。

public static void main(String[] args) throws Exception {    Order order = new Order();    order.setId(0L);    order.setUserId(0L);    order.setOrderNo("1");    order.setAmount(new BigDecimal("0"));    order.setCreateTime("2");    order.setUpdateTime("3");    System.out.println("原始数据:" + order);    Document document = MongoDbUtils.obj2Doc(order);    System.out.println("转换doc数据:" + document);    Order order1 = MongoDbUtils.doc2Obj(document, Order.class);    System.out.println("转换java数据:" + order1);}运行结果:原始数据:Order(id=0, userId=0, orderNo=1, amount=0, createTime=2, updateTime=3)转换doc数据:Document{{id=0, userId=0, orderNo=1, amount=0, createTime=2, updateTime=3}}转换java数据:Order(id=0, userId=0, orderNo=1, amount=0, createTime=2, updateTime=3)

登录后复制

这样一来,我们就不用保留实体类上的转换方法了,剩下的工作就是删代码。

MongoDb 和 Java 对象的互相转换就完成了。我们做了两次迭代,第一次迭代利用了反射,把大量手动 set/get 操作给去掉了;第二次迭代在原来的基础上,加入了泛型的应用,又去掉了一堆重复代码。

以上就是Java使用反射,把对象转换成 MongoDb 的结构的详细内容,更多请关注【创想鸟】其它相关文章!

版权声明:本文内容由互联网用户自发贡献,该文观点仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌抄袭侵权/违法违规的内容, 请发送邮件至253000106@qq.com举报,一经查实,本站将立刻删除。

发布者:PHP中文网,转转请注明出处:https://www.chuangxiangniao.com/p/2604256.html

(0)
上一篇 2025年3月6日 19:50:26
下一篇 2025年2月26日 02:29:01

AD推荐 黄金广告位招租... 更多推荐

相关推荐

  • 详谈Java设置session超时(失效)的时间

    免费学习推荐:java基础教程 在一般系统登录后,都会设置一个当前session失效的时间,以确保在用户长时间不与服务器交互,自动退出登录,销毁session 具体设置的方法有三种: 1.在web容器中设置(以tomcat为例) 在tomc…

    2025年3月6日
    200
  • 简单介绍Java Servlet程序

    本篇文章给大家带来了关于java的相关知识,其中主要整理了servlet的相关问题,servlet运行在服务端(tomcat)的java程序。是sun公司的一套规范,就是动态资源,用来接收客户端的请求,处理请求,响应给浏览器的动态资源,下面…

    2025年3月6日 编程技术
    200
  • Java Web动态网站开发教程

    一、Tomcat安装 下载网址:http://archive.apache.org/dist/tomcat/         tomcat版本:64位 8.5.31 立即学习“Java免费学习笔记(深入)”;         2.Tomca…

    2025年3月6日 编程技术
    200
  • java开发是前端还是后端

    java开发是后端,不是前端;java是一门面向对象的编程语言,也是最常见的后端开发语言之一,后端主要是让服务器、应用、数据库能够彼此交互,需要考虑如何实现功能、数据的存取、平台的稳定性与性能等,常用的脚本语言有php、java、pytho…

    2025年3月6日
    200
  • spring boot框架特点是什么

    特点是:1、可以创建独立的Spring应用程序,并且基于其Maven或Gradle插件,可以创建可执行的JARs和WARs;2、使用嵌入式的Servlet容器(例Tomcat、Jetty等),应用无需打成WAR包;3、提供starter简化…

    2025年3月6日
    200
  • 一起聊聊怎么使用Nginx部署TienChin项目

    本篇文章就来手把手教小伙伴们部署 tienchin 项目,一起把这个项目跑起来,看看到底是个什么样的项目。 小伙伴们知道,对于这种前后端分离的项目,我们在实际部署的时候,可以按照前后端分离的方式来部署,也可以按照前后端不分的方式来部署。接下…

    2025年3月6日 编程技术
    200
  • 怎么使用Java IO流和网络制作一个简单的图片爬虫

    Java IO流和网络的简单应用 最近看到了 url 类的用法,简单的做了一个java 版的爬虫。发现还挺有趣的,就拿出来分享一下。通过关键字爬取百度图片,这个和我们使用搜索引擎搜索百度图片是一样的,只是通过爬虫可以学习技术的使用。(这个程…

    2025年3月6日 编程技术
    200
  • 宝塔面板怎么部署java项目

    1、安装Java项目管理器,在宝塔面板的软件商店,我们输入“Java”,注意第一个字母一定要大写。 2、单击,操作中的“安装”,然后点“确定”按钮。安装过程是非常快的,安装成功后,让它首页显示。 3、单击设置操作,在Java项目管理器中的版…

    2025年3月6日
    200
  • Java多线程的使用及实现方法

    1、应用场景 (1)普通浏览器和网络服务(现在写的网络是帮你完成线程控制的中间部件),网络处理请求,各种专用服务器(比如游戏服务器) (2)servlet多线程。 (3)FTP下载,多线程操作文件。 (4)数据库中使用的多线程。 (5)to…

    编程技术 2025年3月6日
    200
  • Java类加载器与类加载过程的概述

    1. 类加载过程 加载 通过类的全限定名(包名 + 类名),获取到类的.class文件,加载到元空间。 链接 验证:检验.class文件的安全性 准备:为静态类型变量分配内存并设置默认值 解析:将常量池内的符号引用转换为直接引用,符号引用指…

    2025年3月6日
    200

发表回复

登录后才能评论