表示XML中的数据
XML只是一种文本文件格式;它没有成为数据存储或者数据管理的媒介的继承能力。XML数据模型是脆弱的,它的类型系统复杂且低能,它的数据完整性几乎完全程序化,并且它还引入了几十年前就淘汰了的分层数据结构。然而,XML格式的数据对于在Java中使用却很在吸引力;因为我们有一些好工具。例如,可以用XSLT转换XML数据,这是我们认为最佳的使用案例之一。Hibernate没有内建的功能来存储XML格式的数据;它依赖于关系表示和SQL,这种策略的好处应该很清楚。另一方面,Hibernate能够以XML格式把数据加载和呈现给应用程序的开发人员,它允许你使用一组复杂的工具,而无需任何额外的转换步骤。
假设你在默认的POJO模式下工作,并且很快想要获得一些以XML表示的数据。用EntityMode.DOM4J打开一个临时的Session:
Session dom4jSession = session.getSession(EntityMode.DOM4J);
Element userXML = (Element) dom4jSession.get(UserPojo.class,new Long(1));
此处返回的是一个dom4j Element,可以用这个dom4j API来读取和操作它。例如,可以用下列片段把它很漂亮地打印到控制台:
try {
OutputFormat format = OutputFormat.createPrettyPrint();
XMLWriter writer = new XMLWriter(System.out, format);
writer.write(userXML);
} catch (UnsupportedEncodingException e) {
e.printStackTrace();
} catch (IOException e) {
e.printStackTrace();
}
假设你重用来自前面那些例子中的POJO类和数据,你会看到一个UserPojo实例和两个ItemPojo实例。
<UserPojo>
<id>1</id>
<username>zhangsan</username>
<itemsForSale>
<Item>
<id>2</id>
<initialPrice>99</initialPrice>
<description>An item for auction</description>
<seller>1</seller>
</Item>
<Item>
<id>3</id>
<initialPrice>1000</initialPrice>
<description>Another item for auction</description>
<seller>1</seller>
</Item>
</itemsForSale>
</UserPojo>
注意:此时,如果你运行,应该会报错JVM溢出异常,解决方案
1)一方集合设置embed-xml="true"(是否包含xml,Yes)
2)多方设置embed-xml="false"(是否包含xml,No)
可以通过把node属性添加到Hibernate映射元数据来改变这个默认的XML表示法:
<hibernate-mapping package="cn.jbit.entity">
<class name="ItemPojo" table="TBL_ITEM_ENTITY" node="item">
<id name="id" column="ITEM_ID" type="long" node="@id">
<generator class="sequence">
<param name="sequence">SEQ_ITEM_ENTITY_ID</param>
</generator>
</id>
<property name="initialPrice" type="big_decimal" column="INIT_PRICE" node="item-details/@inital-price" />
<property name="description" type="string" column="DESCRIPTION" node="item-details/@description" />
<many-to-one name="seller" class="UserPojo" column="USER_ID" embed-xml="false" node="@seller-id" />
</class>
<class name="UserPojo" table="TBL_USER_ENTITY">
<id name="id" column="USER_ID" type="long" node="@id">
<generator class="sequence">
<param name="sequence">SEQ_USER_ENTITY_ID</param>
</generator>
</id>
<property name="username" type="string" column="UNAME" node="@username" />
<bag name="itemsForSale" inverse="true" cascade="all" embed-xml="true" node="item-for-sale">
<key column="USER_ID" />
<one-to-many class="ItemPojo" />
</bag>
</class>
</hibernate-mapping>
每一个node属性都定义了XML表示法:
1)<class>映射中的node="name"属性,给该实体定义了XML元素的名称。
2)任何属性映射中的node="name"属性,指定属性内容应该表示为给定名称的XML元素文本。
3)任何属性映射中的node="@name"属性,指定属性内容应该表示为给定名称的XML属性值。
4)任何属性映射中的node="name/@attname"属性,指定属性内容应该在给定名称的一个子元素中表示为给定名称的XML属性值。
更新过的映射产生下列你之前已经见过的相同数据的XML表示法:
<UserPojo id="1" username="zhangsan">
<item-for-sale>
<item id="1" seller-id="1">
<item-details inital-price="100" description="description 1"/>
</item>
<item id="2" seller-id="1">
<item-details inital-price="400045" description="description 2"/>
</item>
</item-for-sale>
</UserPojo>
最后,以XML表示的数据是事务和持久化的,因此你可以修改被查询的XML元素,并让Hibernate更新底层的表:
Element itemXML = (Element) dom4jSession.get(ItemPojo.class,new Long(2));
itemXML.element("item-details").attribute("inital-price").setValue("100000");
dom4jSession.flush();//Hibernate executes UPDATES 可以理解为本来应该延迟至事务提交修改,而现在立刻执行修改
Element userXML = (Element) dom4jSession.get(UserPojo.class,new Long(1));
Element newItem = DocumentHelper.createElement("item");
Element newItemDetails = newItem.addElement("item-details");
newItem.addAttribute("seller-id", userXML.attribute("id").getValue());// 设置关联关系
// 添加商品详细信息
newItemDetails.addAttribute("inital-price", "9999");
newItemDetails.addAttribute("description", "描述信息");
dom4jSession.save(Item.class.getName(), newItem);
dom4jSession.flush();
最后,注解如果你喜欢,可以同时使用所有三种内建的实体模式。可以映射领域模型的一个静态的POJO实现,为一般的用户界面切换到动态的映射,并把数据导到XML里面。或者,可以编写一个没有任何领域类的应用,只有动态的映射和XML。可是,必须提醒你,软件行业中的原型经常意味着,客户以这个没有人想要抛弃的原型而告终——你愿意买一辆样板车吗?强烈建议你依赖静态的领域模型,如果要创建可维护的系统的话。
后面不再考虑动态的模型或者XML表示法。焦点放在了静态的持久化类以及它们的映射方式上。
总结一下:
学到后面,感觉概念有点稍多,又是一个人独自学的,进度可能有点慢哦哦。这章内容,主要有领域模型分离横切关注点,接着就是实体编程模型(POJO、JPA实体编程模型),有了模型,当然是选择映射方式咯(1、XML映射文件 2、JDK 5.0注解 3、XDoclet),还有像XML映射元数据可以被全局定义,XML点位符的使用等等。。。可以说东西很多,希望大家也能好好掌握。