JAXB –新手的观点,第1部分
我知道你們很多人已經在想什么了,所以讓我們擺脫它:“ JAXB? 如XML? 來吧,所有很棒的孩子都在使用JSON。”
關于XML與JSON的爭論以及許多促成它的論據(jù)都已被很好地記錄在案。 我不會花很多時間在這里重新整理它們。 我相信每種格式都有其用途,但是即使您處在“從未有過XML”陣營中,您仍然可能想繼續(xù)閱讀,因為我討論的觀察和技術應該同樣適用于與Jackson進行JSON數(shù)據(jù)綁定(或類似工具)。
在第1部分中,我描述了一種簡單的使用模式,該模式將JAXB的數(shù)據(jù)綁定功能與JPA配對。 當然,兩者之間的交互并不總是那么簡單,因此在第2部分中,我將研究如何解決可能遇到的一些復雜問題。
問題
在我當前的項目中,我們正在構建一套Java應用程序,以管理制造過程中物料的轉移。 我們決定“從外而內”構建,以在任何給定的迭代之后促進面向用戶的演示。 因此,在第一個迭代中,我們使用硬編碼的虛擬數(shù)據(jù)構建了一些屏幕。 然后,在每次后續(xù)迭代中,我們都會在屏幕后面添加更多基礎架構和邏輯。
為了使早期的演示更具交互性,我們決定為中央應用程序創(chuàng)建一個“測試控制臺”。 一個人在控制臺上鍵入命令可以模擬系統(tǒng)“已實現(xiàn)網絡”部分的行為。 借助Antlr 4之類的工具可以簡化命令解析,構建控制臺的成本是適中的,并且我們認為使用控制臺進行測試和診斷具有長期價值。
我們已經達到了需要由另一個應用程序的數(shù)據(jù)來驅動系統(tǒng)行為的地步。 負責創(chuàng)建和維護此數(shù)據(jù)的“其他應用”尚未編寫,并且不會使用一段時間,因此我們需要一種通過控制臺加載示例數(shù)據(jù)的方法。
選件
本質上,我們的任務是構建(或利用)數(shù)據(jù)加載器。 我們選擇XML作為文件的可能格式,然后瀏覽我們的團隊通常會熟悉的工具列表。
DBUnit具有數(shù)據(jù)加載功能(旨在設置可重復的測試條件)。 它支持兩種不同的XML模式(“平面”和“完整”),每種模式顯然都是面向表的。 它還提供了替換變量,因此我們可以構建模板文件并允許控制臺輸入設置最終值。
我對以這種方式使用單元測試工具有些保留,但是在團隊的箭袋中,箭頭可能是最合適的。 不管是好是壞,我第一次嘗試使用它都沒有成功(結果是我看的是DBUnit API的錯誤部分),這使我想出了一些新的思路。
我們已經有一種方法(即Hibernate)將數(shù)據(jù)推送到我們的數(shù)據(jù)庫中。 因此,當我用“如何從XML文檔創(chuàng)建實體實例”來表述問題時,JAXB顯然是競爭者。 我很高興發(fā)現(xiàn)Java附帶了JAXB實現(xiàn),因此我開始嘗試一下。
新人的觀點
從未使用過JAXB,所以我開始進行一些研究。 我發(fā)現(xiàn)的許多材料都涉及從XML模式生成Java類。 這不足為奇-這是該工具可以完成的大部分工作-但就我而言,我想將數(shù)據(jù)綁定到現(xiàn)有的Hibernate映射域類。 這導致可能會更加令人驚訝:我發(fā)現(xiàn)一些最全面的教程似乎并沒有預料到這種用法。 我認為這很好地說明了您對工具的初步假設可以影響您的想法和使用方式。
如果像幾個在線資源一樣,首先將JAXB與DOM進行比較,那么將編組操作的輸出視為需要遍歷和處理的文檔樹是很自然的,也許會將相關數(shù)據(jù)復制到并行的層次結構中。域對象。 遍歷和處理(至少在概念上)可能比使用DOM樹要容易(但從概念上來說),但是要權衡,您必須保持兩個類的層次結構直,這需要謹慎的命名約定。
毫無疑問,用例恰恰是必要的,但該工具不僅限于這種方法。 如果您相反地比較JAXB和Hibernate(作為將數(shù)據(jù)從外部源加載到您的域對象中的一種方式),那么自然會問“為什么我不能同時使用一組域對象?” 您至少可以在某些時候稍加注意。
簡單案例
在這些示例中,我將直接使用JAXB API。 我們只需撥打幾個簡單的電話即可完成我們的任務,因此這相當簡單。 值得注意的是,Spring確實也提供JAXB集成,尤其是如果您在整個應用程序中都使用Spring,則它提供的配置方法可能是更可取的。
假設您有一個EMPLOYEE表。 每個員工都有唯一的數(shù)字ID和名稱。 如果將注釋用于ORM映射數(shù)據(jù),則可能具有如下域類:
@Entity @Table(name=”EMPLOYEE”) public class Employee {@Id@Column(name=”EMPLOYEE_ID”)private Integer employeeId;@Column(name=”FIRST_NAME”)private String firstName;@Column(name=”LAST_NAME”)private String lastName;// … getters and setters … };現(xiàn)在,我們要讓用戶提供一個Employee.xml數(shù)據(jù)文件。 假設我們沒有需要遵循的特定XML模式,那么我們不妨看看JAXB對類的默認處理是什么。 因此,我們將從最小的步驟開始,以將一個Employee實例“封送”到XML文檔中。 如果對結果文檔的外觀感到滿意,我們將交換解組代碼; 如果沒有,我們可以考慮自定義映射。
首先,我們需要配置一個JAXBContext實例以與我們的域類一起使用。
JAXBContext jaxb = JAXBContext.newInstance(Employee.class);順便說一句,我們可以傳入包含類的包的名稱,而不是將類對象傳遞給newInstance(),只要每個包都包含一個jaxb.in??dex文件,該文件列出了要使用的類或ObjectFactory類,以及用于創(chuàng)建域類(和/或包裝它們的JAXBElements)實例的方法。 如果您需要大量不相關的域類的XML映射,則此方法可能更可取。
JAXBContext具有創(chuàng)建編組器(創(chuàng)建表示對象的XML文檔)和解組器(實例化對象并從XML文檔中的數(shù)據(jù)初始化它們)的方法。 我們可以像這樣檢查Employee類的默認映射:
Employee employee = new Employee();employee.setEmployeeId(37);employee.setFirstName(“Dave”);employee.setLastName(“Lister”);Marshaller marshaller = jaxb.createMarshaller();marshaller.setProperty(Marshaller.JAXB_FORMATTED_OUTPUT, true); marshaller.marshal(employee, System.out);(嚴格來說,setProperty()調用不是必需的,但會使輸出更易于理解。)如果嘗試運行此代碼,則會收到異常消息,告訴我們尚未識別出根元素。 為了解決這個問題,我們將@XmlRootElement批注添加到Employee類中。
@XmlRootElement @Entity @Table(name=”EMPLOYEE”) public class Employee {@Id@Column(name=”EMPLOYEE_ID”)private Integer employeeId;@Column(name=”FIRST_NAME”)private String firstName;@Column(name=”LAST_NAME”)private String lastName;// … getters and setters … };默認情況下,編組器將映射每個公共bean屬性(getter / setter對)和每個公共字段。 因此,如果我們的Employee類具有您期望的getter和setter,那么我們的輸出應類似于以下內容:
<?xml version=”1.0” encoding=”UTF-8” standalone=”yes”?> <employee><employeeId>37</employeeId><firstName>Dave</firstName><lastName>Lister</lastName> </employee>請注意,下面的元素將采用任意順序。 (在我的測試中,這是按字母順序排列的。)在這種情況下,效果很好,但是如果沒有,我們可以使用@XmlType注釋強制執(zhí)行該順序。 默認情況下,解組器將以任何順序獲取元素。
JAXB很高興不了解JPA批注,而Hibernate(或您可能使用的任何JPA提供程序)將不理會JAXB批注,因此,我們現(xiàn)在可以通過簡單地要求JAXB從文件中解組數(shù)據(jù)來將XML文件中的數(shù)據(jù)加載到數(shù)據(jù)庫中,將結果對象傳遞給JPA提供程序。 解組代碼如下所示:
JAXBContext jaxb = JAXBContext.newInstance(Employee.class); Unmarshaller unmarshaller = jaxb.createUnmarshaller(); File xmlFile = /* … */; Employee employee = unmarshaller.unmarshal(xmlFile);默認情況下,如果從XML中省略了表示bean屬性之一的元素,則不會設置該屬性。 因此,例如,如果我們的JPA映射包括自動生成employeeId,則<employee>元素僅需要包含<firstName>和<lastName>。
好…
從理論上講,就是這樣。 (如果您知道理論和實踐之間的區(qū)別,則要額外加分。)幾個注釋和可能的十幾行代碼足以讓您入門。 另外一個好處是,您可以在一個帶注釋的.java文件中查看所有數(shù)據(jù)表示形式(XML,數(shù)據(jù)庫和Java對象)之間的關系。
不太好…
上面的例子很簡單,可以涵蓋大量的基本用例。 但是大多數(shù)真實的數(shù)據(jù)模型都包含一對多關系和組合鍵之類的東西,它們增加了您可能會或可能不會看到的皺紋。 在第2部分(計劃于2014年8月25日)中,我將介紹我遇到的一些復雜問題,并討論解決每個復雜問題的合理簡單方法。
翻譯自: https://www.javacodegeeks.com/2014/07/jaxb-a-newcomers-perspective-part-1.html
總結
以上是生活随笔為你收集整理的JAXB –新手的观点,第1部分的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: 《碧海黑帆》游戏失去第三位创意总监,育碧
- 下一篇: JavaFX技巧6:使用透明颜色