真实的国产乱ⅩXXX66竹夫人,五月香六月婷婷激情综合,亚洲日本VA一区二区三区,亚洲精品一区二区三区麻豆

成都創(chuàng)新互聯(lián)網(wǎng)站制作重慶分公司

Java如何使用反射把對(duì)象轉(zhuǎn)換成MongoDb的結(jié)構(gòu)-創(chuàng)新互聯(lián)

這篇文章給大家分享的是有關(guān)Java如何使用反射把對(duì)象轉(zhuǎn)換成MongoDb的結(jié)構(gòu)的內(nèi)容。小編覺得挺實(shí)用的,因此分享給大家做個(gè)參考。一起跟隨小編過來看看吧。

專注于為中小企業(yè)提供成都做網(wǎng)站、成都網(wǎng)站建設(shè)、成都外貿(mào)網(wǎng)站建設(shè)服務(wù),電腦端+手機(jī)端+微信端的三站合一,更高效的管理,為中小企業(yè)麻城免費(fèi)做網(wǎng)站提供優(yōu)質(zhì)的服務(wù)。我們立足成都,凝聚了一批互聯(lián)網(wǎng)行業(yè)人才,有力地推動(dòng)了1000多家企業(yè)的穩(wěn)健成長(zhǎng),幫助中小企業(yè)通過網(wǎng)站建設(shè)實(shí)現(xiàn)規(guī)模擴(kuò)充和轉(zhuǎn)變。

反射是 Java 的一個(gè)高級(jí)技巧,大量地用在各種開源項(xiàng)目上。比如,Spring、Tomcat、Jetty 等等項(xiàng)目中,都大量地用到了反射。

作為 Java 程序員,我們?nèi)绻煤梅瓷?,不但能提高自己的技術(shù)水平,還能開發(fā)出更好的項(xiàng)目。

然而,雖然很多人聽說過反射,但卻不知道應(yīng)該用在哪里。

那么,我們就從實(shí)際工作出發(fā),使用反射,把對(duì)象轉(zhuǎn)換成 MongoDb 的數(shù)據(jù)結(jié)構(gòu)。當(dāng)你在搞懂這個(gè)例子后,就能明白反射是怎么個(gè)用法。

需求分析

在電商系統(tǒng)中,一些數(shù)據(jù)要保存到 MongoDb 中,以此來提高查詢的性能。但在此之前,我們必須把數(shù)據(jù)先轉(zhuǎn)換成 MongoDb 的結(jié)構(gòu),也就是把 Java 對(duì)象轉(zhuǎn)換成 Document。

比如,訂單信息要存到 MongoDb 中,就得把訂單對(duì)象轉(zhuǎn)換成 Document。

可這樣一來,每個(gè)實(shí)體類都得開發(fā)一個(gè) 2Doc() 方法。這個(gè)方法毫無技術(shù)含量,就是把各種字段 put 到 Document 里面。而且一旦字段多了,一不留神就會(huì)寫錯(cuò)代碼,你感受一下。

public class Order {
    private Long id;
    private Long userId;
    private String orderNo;
    private BigDecimal amount;
    private String createTime;
    private String updateTime;
    // 省略無數(shù)字段
    
    // 轉(zhuǎn)換方法:訂單轉(zhuǎn)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());
        // 省略無數(shù)put...

        return doc;
    }
}

除此之外,我們還得從 MongoDb 中取數(shù)據(jù),把 Document 轉(zhuǎn)換回 Java 對(duì)象,你再感受一下。

public class Order {
    private Long id;
    private Long userId;
    private String orderNo;
    private BigDecimal amount;
    private String createTime;
    private String updateTime;
    // 省略無數(shù)字段
    
    // 轉(zhuǎn)換方法:doc轉(zhuǎn)訂單
    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"));
        // 省略無數(shù)set...

        return order;
    }
}

光是一個(gè)訂單類都這么麻煩了,何況這樣的類不止一個(gè),而且項(xiàng)目總有新需求,如果一個(gè)字段改了,那你麻煩大了,說不定要把整個(gè)項(xiàng)目翻一遍。

因此,為了少出錯(cuò),必須優(yōu)化這兩個(gè)轉(zhuǎn)換方法,而這次優(yōu)化用到了 Java 的兩個(gè)高級(jí)特性:反射、泛型。為了讓大家更直觀的了解,我將分成兩個(gè)版本迭代。

第一版,利用反射,簡(jiǎn)化實(shí)體類的轉(zhuǎn)換方法;

第二版,利用泛型、反射,提取 MongoDb 工具類;

接下來,我們就一步步迭代吧~

利用反射,簡(jiǎn)化實(shí)體類的轉(zhuǎn)換方法

在第一版的迭代中,我們要簡(jiǎn)化實(shí)體類的兩個(gè)轉(zhuǎn)換方法。

我們先從 Java 對(duì)象轉(zhuǎn) Document 開始,還是以 Order 類為例。

首先,我們通過反射,獲取到訂單類的所有字段信息;然后,使用循環(huán)遍歷這些字段;最后,在循環(huán)中,我們放開字段的訪問權(quán)限,把字段 put 到 Document 里面。

public class Order {
    // ...省略無數(shù)字段

    public Document order2Doc(Order order) throws Exception {
        Document doc = new Document();

        // 獲取所有字段:通過 getClass() 方法獲取 Class 對(duì)象,然后獲取這個(gè)類所有字段
        Field[] fields = order.getClass().getDeclaredFields();
        for (Field field : fields) {
            // 開放字段操作權(quán)限
            field.setAccessible(true);
            // 設(shè)置值
            doc.put(field.getName(), field.get(order));
        }

        return doc;
    }
}

你可以看到,經(jīng)過反射改造后,代碼簡(jiǎn)單了很多。一個(gè)對(duì)象無論有多少個(gè)字段,要寫多少 put 操作,只要這幾行代碼就能搞定。Java 對(duì)象轉(zhuǎn)成 MongoDb 的結(jié)構(gòu),看起來也不那么麻煩了。

照著這個(gè)思路,我們?cè)賮砀脑斓诙€(gè)方法,Document 轉(zhuǎn) Java 對(duì)象。

public class Order {
    // ...省略無數(shù)字段

    public Order doc2Order(Document doc) throws Exception {
        Order order = new Order();

        for (String key : doc.keySet()) {
            // 獲取字段
            Field field = order.getClass().getDeclaredField(key);
            // 開放字段操作權(quán)限
            field.setAccessible(true);
            // 設(shè)置值
            field.set(order, doc.get(key));
        }

        return order;
    }
}

首先,我們使用循環(huán)遍歷 Document;在循環(huán)中,使用反射獲取相應(yīng)的字段,再放開字段的訪問權(quán)限,把 Document 的值設(shè)置到對(duì)象的字段里。

到了這兒,我們利用反射,簡(jiǎn)化了兩個(gè)實(shí)體類的轉(zhuǎn)換方法,第一版的迭代基本完成了。剩下的工作,就是復(fù)制粘貼,把各個(gè)類重新改造一遍。

然而,經(jīng)過這一版迭代,雖然減少了很多工作,但依然有很多不合理的地方。

首先,重復(fù)代碼還是很多。每個(gè)實(shí)體類都有兩個(gè)轉(zhuǎn)換方法,但這兩個(gè)方法的核心邏輯是一樣的,完全沒必要到處復(fù)制。

然后,這不是實(shí)體類應(yīng)該承擔(dān)的功能。實(shí)體類只負(fù)責(zé)短暫保留數(shù)據(jù),不負(fù)責(zé)任何持久化功能。你把數(shù)據(jù)存到哪里,該轉(zhuǎn)換成什么數(shù)據(jù)結(jié)構(gòu),這和實(shí)體類沒什么關(guān)系。

換句話說,我們還得做第二次迭代。

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

簡(jiǎn)單來說,泛型是一種風(fēng)格或范式,你不用一開始就指明具體的參數(shù)類型,而是在使用的時(shí)候再確定參數(shù)類型。

如果把泛型、反射結(jié)合在一起,能幫我們減少很多重復(fù)代碼。

我們來看看,該怎么做第二次迭代?

先從 Java 對(duì)象轉(zhuǎn) Document 開始。我們先聲明一個(gè)泛型方法;然后,通過反射,獲取泛型類的所有字段信息,再使用循環(huán)遍歷這些字段;最后,在循環(huán)中,把字段 put 到 Document 里面。

public class MongoDbUtils {

    // 定義泛型方法:
    // 1. 在返回值前,聲明泛型參數(shù) <參數(shù)名>;
    // 2. 傳入?yún)?shù)時(shí),指定一個(gè)泛型參數(shù)
    public static  Document obj2Doc(T obj) throws Exception {
        Document doc = new Document();

        // 獲取所有字段:通過 getClass() 方法獲取 Class 對(duì)象,然后獲取這個(gè)類所有字段
        Field[] fields = obj.getClass().getDeclaredFields();
        for (Field field : fields) {
            // 開放字段操作權(quán)限
            field.setAccessible(true);
            // 設(shè)置值
            doc.put(field.getName(), field.get(obj));
        }

        return doc;
    }
}

在加入泛型后,重復(fù)代碼大量減少了,實(shí)體類不用再單獨(dú)寫2Doc()方法了。在使用的時(shí)候,只要調(diào)用MongoDbUtils.obj2Doc()就行。

按照同樣的思路,我們繼續(xù)來改造第二個(gè)方法,Document 轉(zhuǎn) Java 對(duì)象。

public class MongoDbUtils {

    // 定義泛型方法:
    // 1. 在返回值前,聲明泛型參數(shù) <參數(shù)名>;
    // 2. 傳入?yún)?shù)必須是 Class,但這個(gè) Class 是泛型參數(shù),不限制類型
    public static  T doc2Obj(Document doc, Class clazz) throws Exception {
        // 實(shí)例化泛型對(duì)象
        T obj = clazz.newInstance();

        for (String key : doc.keySet()) {
            // 獲取字段
            Field field = clazz.getDeclaredField(key);
            // 開放字段操作權(quán)限
            field.setAccessible(true);
            // 設(shè)置值
            field.set(obj, doc.get(key));
        }

        return obj;
    }
}

首先,我們定義實(shí)例化一個(gè)泛型對(duì)象;然后,我們使用循環(huán)遍歷 Document;最后,在循環(huán)中,使用反射獲取相應(yīng)的字段,把 Document 的值設(shè)置到泛型對(duì)象的字段里。

第二版的迭代就基本完成了。我們?cè)诘谝话娴幕A(chǔ)上,加入了泛型,得到了一個(gè)工具類MongoDbUtils,這個(gè)工具類得到結(jié)果和以前完全一樣,你可以看下測(cè)試代碼。

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("原始數(shù)據(jù):" + order);

    Document document = MongoDbUtils.obj2Doc(order);
    System.out.println("轉(zhuǎn)換doc數(shù)據(jù):" + document);

    Order order1 = MongoDbUtils.doc2Obj(document, Order.class);
    System.out.println("轉(zhuǎn)換java數(shù)據(jù):" + order1);
}

運(yùn)行結(jié)果:
原始數(shù)據(jù):Order(id=0, userId=0, orderNo=1, amount=0, createTime=2, updateTime=3)
轉(zhuǎn)換doc數(shù)據(jù):Document{{id=0, userId=0, orderNo=1, amount=0, createTime=2, updateTime=3}}
轉(zhuǎn)換java數(shù)據(jù):Order(id=0, userId=0, orderNo=1, amount=0, createTime=2, updateTime=3)

這樣一來,我們就不用保留實(shí)體類上的轉(zhuǎn)換方法了,剩下的工作就是刪代碼。

MongoDb 和 Java 對(duì)象的互相轉(zhuǎn)換就完成了。我們做了兩次迭代,第一次迭代利用了反射,把大量手動(dòng) set/get 操作給去掉了;第二次迭代在原來的基礎(chǔ)上,加入了泛型的應(yīng)用,又去掉了一堆重復(fù)代碼。

感謝各位的閱讀!關(guān)于Java如何使用反射把對(duì)象轉(zhuǎn)換成MongoDb的結(jié)構(gòu)就分享到這里了,希望以上內(nèi)容可以對(duì)大家有一定的幫助,讓大家可以學(xué)到更多知識(shí)。如果覺得文章不錯(cuò),可以把它分享出去讓更多的人看到吧!


新聞標(biāo)題:Java如何使用反射把對(duì)象轉(zhuǎn)換成MongoDb的結(jié)構(gòu)-創(chuàng)新互聯(lián)
鏈接分享:http://weahome.cn/article/spgph.html

其他資訊

在線咨詢

微信咨詢

電話咨詢

028-86922220(工作日)

18980820575(7×24)

提交需求

返回頂部