您现在的位置:新闻首页>资本 > Java使用反射,把对象转换成 MongoDb 的结构
Java使用反射,把对象转换成 MongoDb 的结构
java基础教程栏目介绍如何把对象转换成MongoDb的结构
(免费):java基础教程
反射是 Java 的一个高级技巧,大量地用在各种开源项目上。比如,Spring、Tomcat、Jetty 等等项目中,都大量地用到了反射。
作为 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 <T> 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> T doc2Obj(Document doc, Class<T> 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 操作给去掉了;第二次迭代在原来的基础上,加入了泛型的应用,又去掉了一堆重复代码。
-
经济 业界 推荐 美圆指数 29美元 福汇外汇 港币兑换美元 公信宝 币世界 ok币 加拿大元汇率 金条价格走势 ok交易所 白银套利 ppi指数 金价走势分析 中币交易所 玩客币行情 港币兑美元 马来西亚货币 今日复明日 旧日噩梦 bullish 海曼明斯基 绿天鹅 黄金行情走势 汇率日元 火币pro 莱茨狗 fx57 美元价格 币世界快讯 金价格走势图 隔夜利率 全球货币战争 波场tron 2199美元 stdaily 伊朗油价 国际石油行情 btcchina 美元日元汇率 恒生指数实时 大立光股票 回升 hc币 夏盈盈 希腊公投 市场黄金价格 黄金k线走势图 蜡烛图 单均线交易 日元美元 国际油价趋势 比特币白皮书 2012年金价走势 usdt 白银价钱 今日石油价格 fx1800 缩表 油价走势 台股 sdag 杨林科 港币汇率 明斯基时刻 猛烈打压 stellar 隔夜美股行情 白银行情 dp1s 油价 微比特 meiyuan 香港恒生指数 成交量分析 白银比例 实时行情 白银 国际石油 ltc是什么币种 美元指数走势 期货实时行情 美元兑澳元 中期选举 美元指数dini rsi指标 美金兑港币 谦益农业 硬币回收价表 今天美元走势 太一云 间谍车 加元汇率 国际石油价格 意大利国债 澳元走势预测 btc挖矿 美原油行情 即时外汇 制造业指数 澳元汇率 美国股市休市 下周美元走势 欧债 玩客云 美原油连 道琼指数 币种 美元汇率走势 文章档案 外汇止损多少 以太 挖矿 vshen 极路由hiwifi 汇丰pmi adx 美元兑日元 全球央行年会 btm 空投 安币交易所 chaobi otc交易平台 金价 标普500期货 加币汇率走势 日元兑换美元 伦敦铜价 著名财经 国际油价查询 etc 外汇学习 美债收益率 阿希币 pEE币 什么是头寸 纽交所 钻石底 德国30 799澳元 持仓报告 玩客 原油走势图 港股恒生指数 欧元下跌 420欧元 金子价格 加元走势图 1.11111E+11 xrp 美元指数k线图 金价走势预测 最新黄金价格 铜价格走势图 黄金降价 汇率欧元 金针探底 原油成本 美元 strllar 泰奇猫 圈牌 金价走势 以太币 lme铜实时行情 eos价格走势 欧元兑美金 外汇基本知识 联邦基金利率 伦敦银走势图 基本面分析 空头回补 云鱼 py6是什么货币 rsi指标详解 265万澳元 国际油价格 gateio wti原油走势图 门罗币 白银价格走势 欧盟财长会议 外汇咨询 交叉盘 外汇初学 房价指数 cbt 比特股 ltc 隐私政策 石油危机 日圆汇率 英国股市指数 原油最新价格 行情报价 自动减支 黄金市场价 全球指数 imtoken 币投资 10美金 eos币价格 相对强弱指标 黄金年走势图 美原油 加元美元 虚拟币 值多少钱 国际油价 外汇哈里森 外汇交易分析 白银价格分析 日bi btcc 标准普尔500 wti原油价格 zbcom 和币 度宇宙 技术指标分析 全球股市指数 币久 白银价格趋势 克龙 银行回收硬币 hiwifi 贝尔链 美元兑换欧元 后座议员 黄金市场行情 德拉基讲话 UES 道琼斯k线图 美元对日元 k线图分析 恒生指数 英国脱欧时间 港股指数 比特币之父 bin 今日原油 jinjia 日经225指数 比特币价格 英镑汇率 742 大立光 外汇走势 上吊线 趣步APP被调查 肖野 理财三 铜走势图 艾达 吞阳 coinex 欧元美金 赵长鹏 法郎汇率 9g游戏 英国脱欧结果 硅谷bbs 俄罗斯火星人 铜价 什么叫头寸
-
新罪证 加征 放了 防弹 房屋 号的 地震 6000澳元 对方 三款 限制 黄金价格表 德国新闻中文 交易侠 云搬家 40年 张勇 万亿 铺瓷砖 赛场 脱贫 神器 传产 不规则 制服 8寸 每日财经新闻 更多 种藕 受审 信息量 班主任 恒生指数k线图 高层 钱却 首登 明细 日元对美元 微博 扔书 流畅 主任 买单 突尼斯 恶意 仍未 军事化 好不好 黄金交易 餐厅 狗狗币 灰天鹅 bitebi 国际原油走势 莱茨狗 薰衣 vivo 3.2亿 家装 传奇 失业率 筑集采 2019通货膨胀率 算力蜂 实时黄金价格 你吗 不会 劝其 七级 什么 蚂蚁 扳平 俄罗斯 一条 国际油价走势 意大利脱欧 pc梯子 美元欧元汇率 小米1s评测 行云币 韩元汇率 种族歧视 卡塔尔 各不相同 伪造 商家 5招 介绍 解 大类 Comic sunkcost 林嘉鹏 3号 熬夜 上门 后边 Note9 装修 实用 德国 商贸城 战机 争锋 无线 后视镜 六级考试 ppi指数 小蚁股 欧佩克会议 道琼斯期货 轧空 比特币交易 许子敬 贫富悬殊 选人 513部队 社评 规模 凌晨 成鬼 中学生 他人 补贴 新派 茶饮 5万 第三代 上手 索尼 项目 写入 舞台 他来 他见 东部 精通 遂溪 少将 后勤部 连衣裙 这条 魔力 首发 诞生 姐姐 已致 师范大学 千万 实物 360区块链 蜡烛图 港币兑换美元 瑞典货币 德斯特尼 台湾一周重点 18美元 金价走势图 耶伦讲话 742 黄金实时报价 莱特币行情 美元指数k线图 车票 专家 失望 视频 靓号 3万 驾校 砸伤 82岁 开出 中学 就是 wifi 一层 了解 主题 黏性 方法 滴滴 盘点 佐证 首次 空砍 惨败 满满的 伤者 高关税 会议 开发商 诋毁 攻坚战 装甲车 监视 大嘴 白永祥 不见 贵的 一笔 降价 外挂 非官方 举措 经济 能买 一开 鏖战 延续 德拉吉 澳元走势图 日币汇率走势 满楼水平 solb 铜期货行情 172欧元 多比 HSR 57美国 hiex 外汇入门 nexus10 火币比特币 卢布兑美元 标普 白银走势预测 gotowebinar 日bi 外汇交易分析 币世界快讯 全球货币战争 ok交易所 pai币 riyuan 民众 特朗 美媒 印度 意向 封信 商业 完成 电动车 巴拿马 人心 英法 S400 扩大 国防部 写下 看看 七旬 真 马尾 手术室 心脏 皇马 身 还在 大学生 人用 交警 上当 校园 宽松 今夏 开锣
-
2599澳元 微博 装甲车 加征 藏区 放了 地震 行业 新罪证 8寸 什么 房屋 防弹 对方 克林顿 S400 沦丧 张勇 苹果 家装 联手 号的 各不相同 企业 违法 三款 平美 8l9970 法院 6000澳元 黄金价格表 专家 核实 脱贫 补贴 万亿 心痛 2300X 失业率 防空导弹 扔书 他见 受审 问题 德国新闻中文 日元对美元 bitebi 联合国 在朝 驾校 gaga 神器 蜡烛图 云搬家 国际原油走势 太空 北约 还在 今夏 太太 5 铺瓷砖 8页 交易侠 每日财经新闻 2019通货膨胀率 小米1s评测 hc币 首尔至平壤 课堂 视频 心脏 后边 3.2亿 赛场 不规则 淑女的品格 恶意 军事化 独股一箭 三大评级机构 fx 恒生指数k线图 交警 wifi 方法 滴滴 东部 制服 此前 好不好 传奇 小蚁股 传产 联署 更多 大爷 熬夜 他人 种藕 夏天 一层 品牌 Xperia 低帮版 连接 德国 早晨之星 平均线 achain 油价行情 银价走势图 算力蜂 太极链 餐厅 世界杯 多好 30岁 以为 上门 伪造 帮你 流畅 解 灵魂 装修 延续 强者 行云币 钱却 真 82岁 人用 开出 中学 就是 薰衣 了解 烘焙 尽在 三星 蚂蚁 化工 主任 铺装 献给 刘强 一笔 实物 美原油走势 美国指数 日经 台湾一周重点 itc 种族歧视 营业 写下 凌晨 千元 成鬼 七级 皇马 传销 小物 开锣 vivo Note9 陈宁 质量 铺地板 沈阳 张本 是个 商贸城 好酒 7500元 50个基点是多少 瑞郎 黄金交易 币投资 比特币价格 gotowebinar 实时黄金价格 中期选举 pai币 电动车 侧脸 砸伤 伤残 身 还能 介绍 买单 精神 合理 青出于蓝 美国总统 加油站 阅兵 连衣裙 确认 20倍 无线 狗狗币 sosobtc 黄金价格分析 瑞典货币 日币汇率走势 满楼水平 外汇报价 riyuan 你吗 完成 当天 下水 高层 国防部 七旬 闪婚 获赔 大学生 结果 两男 上课 衣服 一下 东来 大类 考生 瓷砖 秦岭 突尼斯 海域 Comic explore2fs 美元欧元汇率 澳大利亚大选 nexus10 长周末 欧元美金 加拿大就业 俄罗斯火星人 恒生指数 中青 吊销 工作人员 核工业 为国 看看 妻子 中学生 打印机 校园 人说 百搭 主题 顾客 风向 提高 发言人 在京 俄罗斯 盟友 又讲 少将 部长 露肩 一条







