java基礎(chǔ)教程欄目介紹如何把對象轉(zhuǎn)換成MongoDb的結(jié)構(gòu)
推薦(免費):java基礎(chǔ)教程
反射是 Java 的一個高級技巧,大量地用在各種開源項目上。比如,Spring、Tomcat、Jetty 等等項目中,都大量地用到了反射。
作為 Java 程序員,我們?nèi)绻煤梅瓷?,不但能提高自己的技術(shù)水平,還能開發(fā)出更好的項目。
然而,雖然很多人聽說過反射,但卻不知道應(yīng)該用在哪里。
那么,我們就從實際工作出發(fā),使用反射,把對象轉(zhuǎn)換成 MongoDb 的數(shù)據(jù)結(jié)構(gòu)。當你在搞懂這個例子后,就能明白反射是怎么個用法。
需求分析
在電商系統(tǒng)中,一些數(shù)據(jù)要保存到 MongoDb 中,以此來提高查詢的性能。但在此之前,我們必須把數(shù)據(jù)先轉(zhuǎn)換成 MongoDb 的結(jié)構(gòu),也就是把 Java 對象轉(zhuǎn)換成 Document。
比如,訂單信息要存到 MongoDb 中,就得把訂單對象轉(zhuǎn)換成 Document。
可這樣一來,每個實體類都得開發(fā)一個 2Doc() 方法。這個方法毫無技術(shù)含量,就是把各種字段 put 到 Document 里面。而且一旦字段多了,一不留神就會寫錯代碼,你感受一下。
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 對象,你再感受一下。
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; ????} }
光是一個訂單類都這么麻煩了,何況這樣的類不止一個,而且項目總有新需求,如果一個字段改了,那你麻煩大了,說不定要把整個項目翻一遍。
因此,為了少出錯,必須優(yōu)化這兩個轉(zhuǎn)換方法,而這次優(yōu)化用到了 Java 的兩個高級特性:反射、泛型。為了讓大家更直觀的了解,我將分成兩個版本迭代。
第一版,利用反射,簡化實體類的轉(zhuǎn)換方法;第二版,利用泛型、反射,提取 MongoDb 工具類;
接下來,我們就一步步迭代吧~
利用反射,簡化實體類的轉(zhuǎn)換方法
在第一版的迭代中,我們要簡化實體類的兩個轉(zhuǎn)換方法。
我們先從 Java 對象轉(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?對象,然后獲取這個類所有字段 ????????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)過反射改造后,代碼簡單了很多。一個對象無論有多少個字段,要寫多少 put 操作,只要這幾行代碼就能搞定。Java 對象轉(zhuǎn)成 MongoDb 的結(jié)構(gòu),看起來也不那么麻煩了。
照著這個思路,我們再來改造第二個方法,Document 轉(zhuǎn) Java 對象。
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è)置到對象的字段里。
到了這兒,我們利用反射,簡化了兩個實體類的轉(zhuǎn)換方法,第一版的迭代基本完成了。剩下的工作,就是復(fù)制粘貼,把各個類重新改造一遍。
然而,經(jīng)過這一版迭代,雖然減少了很多工作,但依然有很多不合理的地方。
首先,重復(fù)代碼還是很多。每個實體類都有兩個轉(zhuǎn)換方法,但這兩個方法的核心邏輯是一樣的,完全沒必要到處復(fù)制。
然后,這不是實體類應(yīng)該承擔的功能。實體類只負責短暫保留數(shù)據(jù),不負責任何持久化功能。你把數(shù)據(jù)存到哪里,該轉(zhuǎn)換成什么數(shù)據(jù)結(jié)構(gòu),這和實體類沒什么關(guān)系。
換句話說,我們還得做第二次迭代。
利用泛型、反射,提取 MongoDb 工具類
簡單來說,泛型是一種風格或范式,你不用一開始就指明具體的參數(shù)類型,而是在使用的時候再確定參數(shù)類型。
如果把泛型、反射結(jié)合在一起,能幫我們減少很多重復(fù)代碼。
我們來看看,該怎么做第二次迭代?
先從 Java 對象轉(zhuǎn) Document 開始。我們先聲明一個泛型方法;然后,通過反射,獲取泛型類的所有字段信息,再使用循環(huán)遍歷這些字段;最后,在循環(huán)中,把字段 put 到 Document 里面。
public?class?MongoDbUtils?{ ????//?定義泛型方法: ????//?1.?在返回值前,聲明泛型參數(shù)?<參數(shù)名>; ????//?2.?傳入?yún)?shù)時,指定一個泛型參數(shù) ????public?static?<T>?Document?obj2Doc(T?obj)?throws?Exception?{ ????????Document?doc?=?new?Document(); ????????//?獲取所有字段:通過?getClass()?方法獲取?Class?對象,然后獲取這個類所有字段 ????????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ù)代碼大量減少了,實體類不用再單獨寫 2Doc()
方法了。在使用的時候,只要調(diào)用 MongoDbUtils.obj2Doc()
就行。
按照同樣的思路,我們繼續(xù)來改造第二個方法,Document 轉(zhuǎn) Java 對象。
public?class?MongoDbUtils?{ ????//?定義泛型方法: ????//?1.?在返回值前,聲明泛型參數(shù)?<參數(shù)名>; ????//?2.?傳入?yún)?shù)必須是?Class,但這個?Class?是泛型參數(shù),不限制類型 ????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); ????????????//?開放字段操作權(quán)限 ????????????field.setAccessible(true); ????????????//?設(shè)置值 ????????????field.set(obj,?doc.get(key)); ????????} ????????return?obj; ????} }
首先,我們定義實例化一個泛型對象;然后,我們使用循環(huán)遍歷 Document;最后,在循環(huán)中,使用反射獲取相應(yīng)的字段,把 Document 的值設(shè)置到泛型對象的字段里。
第二版的迭代就基本完成了。我們在第一版迭代的基礎(chǔ)上,加入了泛型,得到了一個工具類 MongoDbUtils
,這個工具類得到結(jié)果和以前完全一樣,你可以看下測試代碼。
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); } 運行結(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)
這樣一來,我們就不用保留實體類上的轉(zhuǎn)換方法了,剩下的工作就是刪代碼。
MongoDb 和 Java 對象的互相轉(zhuǎn)換就完成了。我們做了兩次迭代,第一次迭代利用了反射,把大量手動 set/get 操作給去掉了;第二次迭代在原來的基礎(chǔ)上,加入了泛型的應(yīng)用,又去掉了一堆重復(fù)代碼。
Atas ialah kandungan terperinci Java使用反射,把對象轉(zhuǎn)換成 MongoDb 的結(jié)構(gòu). Untuk maklumat lanjut, sila ikut artikel berkaitan lain di laman web China PHP!

Alat AI Hot

Undress AI Tool
Gambar buka pakaian secara percuma

Undresser.AI Undress
Apl berkuasa AI untuk mencipta foto bogel yang realistik

AI Clothes Remover
Alat AI dalam talian untuk mengeluarkan pakaian daripada foto.

Clothoff.io
Penyingkiran pakaian AI

Video Face Swap
Tukar muka dalam mana-mana video dengan mudah menggunakan alat tukar muka AI percuma kami!

Artikel Panas

Alat panas

Notepad++7.3.1
Editor kod yang mudah digunakan dan percuma

SublimeText3 versi Cina
Versi Cina, sangat mudah digunakan

Hantar Studio 13.0.1
Persekitaran pembangunan bersepadu PHP yang berkuasa

Dreamweaver CS6
Alat pembangunan web visual

SublimeText3 versi Mac
Perisian penyuntingan kod peringkat Tuhan (SublimeText3)

Untuk mengendalikan transaksi JDBC dengan betul, anda mesti terlebih dahulu mematikan mod komit automatik, kemudian melakukan pelbagai operasi, dan akhirnya melakukan atau mengembalikan semula hasilnya; 1. Panggil Conn.SetAutOcommit (palsu) untuk memulakan transaksi; 2. Melaksanakan pelbagai operasi SQL, seperti memasukkan dan mengemaskini; 3. Panggil Conn.Commit () jika semua operasi berjaya, dan hubungi conn.rollback () jika pengecualian berlaku untuk memastikan konsistensi data; Pada masa yang sama, cuba-dengan-sumber harus digunakan untuk menguruskan sumber, mengendalikan pengecualian dengan betul dan menutup sambungan untuk mengelakkan kebocoran sambungan; Di samping itu, adalah disyorkan untuk menggunakan kolam sambungan dan menetapkan mata simpan untuk mencapai rollback separa, dan menyimpan urus niaga sesingkat mungkin untuk meningkatkan prestasi.

Gunakan kelas dalam pakej Java.Time untuk menggantikan kelas lama dan kelas kalendar; 2. Dapatkan tarikh dan masa semasa melalui LocalDate, LocalDateTime dan Tempatan Tempatan; 3. Buat tarikh dan masa tertentu menggunakan kaedah (); 4. Gunakan kaedah tambah/tolak untuk meningkatkan dan mengurangkan masa; 5. Gunakan zoneddatetime dan zonid untuk memproses zon waktu; 6. Format dan parse date string melalui DateTimeFormatter; 7. Gunakan segera untuk bersesuaian dengan jenis tarikh lama apabila perlu; pemprosesan tarikh di java moden harus memberi keutamaan untuk menggunakan java.timeapi, yang memberikan jelas, tidak berubah dan linear

WiredTigerisMongoDB’sdefaultstorageenginesinceversion3.2,providinghighperformance,scalability,andmodernfeatures.1.Itusesdocument-levellockingandMVCCforhighconcurrency,allowingreadsandwritestoproceedwithoutblockingeachother.2.DataisstoredusingB-trees,

Pra-formancetartuptimemoryusage, quarkusandmicronautleadduetocompile-timeprocessingandgraalvsupport, withquarkusoftenperforminglightbetterine serverless scenarios.tyvelopecosyste,

Useembeddingwhentherelationshipison-to-few, dataisAccessedtogether, danfastreadsareneeded; 2.userereferencingwhendealingwithone-to-manyormany-to-manyrelationships, LegarorindependlyqueriedData;

Koleksi Sampah Java (GC) adalah mekanisme yang secara automatik menguruskan ingatan, yang mengurangkan risiko kebocoran ingatan dengan menuntut semula objek yang tidak dapat dicapai. 1.GC menghakimi kebolehcapaian objek dari objek akar (seperti pembolehubah stack, benang aktif, medan statik, dan lain -lain), dan objek yang tidak dapat dicapai ditandakan sebagai sampah. 2. Berdasarkan algoritma penandaan tanda, tandakan semua objek yang dapat dicapai dan objek yang tidak ditandai. 3. Mengamalkan strategi pengumpulan generasi: Generasi Baru (Eden, S0, S1) sering melaksanakan MinorGC; Orang tua melakukan kurang tetapi mengambil masa lebih lama untuk melakukan MajorGC; Metaspace Stores Metadata kelas. 4. JVM menyediakan pelbagai peranti GC: SerialGC sesuai untuk aplikasi kecil; ParallelGC meningkatkan throughput; CMS mengurangkan

GradleisthebetterChoiceFormostNewProjectSduetoitSsuperiorflexibility, Prestasi, danModernToolingSupport.1.Gradle'sGroovy/KOT lindslismoreconciseandexpressivethanmaven'sverbosexml.2.GradleOutPerformsMaveninBuildSpeedWithIncrementalcompilation, BuildCac

Defer digunakan untuk melaksanakan operasi tertentu sebelum fungsi pulangan, seperti sumber pembersihan; Parameter dinilai dengan serta-merta apabila menangguhkan, dan fungsi-fungsi dilaksanakan mengikut urutan terakhir (LIFO); 1. Pelbagai penahanan dilaksanakan dalam urutan terbalik pengisytiharan; 2. Biasanya digunakan untuk pembersihan yang selamat seperti penutupan fail; 3. Nilai pulangan yang dinamakan boleh diubah suai; 4. Ia akan dilaksanakan walaupun panik berlaku, sesuai untuk pemulihan; 5. Elakkan penyalahgunaan menangguhkan gelung untuk mengelakkan kebocoran sumber; Penggunaan yang betul boleh meningkatkan keselamatan kod dan kebolehbacaan.
