清单17:更新持久化类映射的工具类
该类一一执行了下面的操作:
1、对于指定的业务实体,定义其xml映射的位置,并加载到DOM Document对象中,以供进一步操作;
2、查找到Document对象中的元素。我们将在这里存储自定义字段和我们所做的内容变化;
3、将该元素内嵌套的所有元素都删除;
4、对于负责自定义字段存储的组件所包含的任意持久化属性,我们都创建一个特定的document元素,并根据相应的属性为元素定义属性;
5、保存这个新建的映射文件。
虽然我们这里用了XMLUtil类(正如从代码中看到的一样)来处理XML,但是一般而言,可以换成任何一种方式来实现,不过XMLUtil已经足以加载并保存xml文件。
我们的实现如下面的清单所示:
package com.enterra.customfieldsdemo; import org.w3c.dom.Node; import org.w3c.dom.NodeList; import org.w3c.dom.Document; import org.xml.sax.SAXException; import javax.xml.parsers.ParserConfigurationException; import javax.xml.parsers.DocumentBuilderFactory; import javax.xml.parsers.DocumentBuilder; import javax.xml.transform.TransformerException; import javax.xml.transform.TransformerFactory; import javax.xml.transform.Transformer; import javax.xml.transform.OutputKeys; import javax.xml.transform.stream.StreamResult; import javax.xml.transform.dom.DOMSource; import java.io.IOException; import java.io.FileOutputStream; public class XMLUtil { public static void removeChildren(Node node) { NodeList childNodes = node.getChildNodes(); int length = childNodes.getLength(); for (int i = length - 1; i > -1; i--) node.removeChild(childNodes.item(i)); } public static Document loadDocument(String file) throws ParserConfigurationException, SAXException, IOException { DocumentBuilderFactory factory =DocumentBuilderFactory.newInstance(); DocumentBuilder builder = factory.newDocumentBuilder(); return builder.parse(file); } public static void saveDocument(Document dom, String file) throws TransformerException, IOException { TransformerFactory tf = TransformerFactory.newInstance(); Transformer transformer = tf.newTransformer(); transformer.setOutputProperty(OutputKeys.DOCTYPE_PUBLIC, dom.getDoctype().getPublicId()); transformer.setOutputProperty(OutputKeys.DOCTYPE_SYSTEM, dom.getDoctype().getSystemId()); DOMSource source = new DOMSource(dom); StreamResult result = new StreamResult(); FileOutputStream outputStream = new FileOutputStream(file); result.setOutputStream(outputStream); transformer.transform(source, result); outputStream.flush(); outputStream.close(); } } |
清单18:XML处理工具类
测试
我们有了所有必需的运行代码, 现在可以编写测试代码来看看一切到底是怎样工作的。第一个测试创建自定义字段“email”,创建并保存Contact类的实例,并给它定义“email”属性。
首先让我们看一下数据库表tbl_contact,它包括两个字段:fld_id和fld_name。代码如下:
package com.enterra.customfieldsdemo.test; import com.enterra.customfieldsdemo.HibernateUtil; import com.enterra.customfieldsdemo.CustomizableEntityManager; import com.enterra.customfieldsdemo.CustomizableEntityManagerImpl; import com.enterra.customfieldsdemo.domain.Contact; import org.hibernate.Session; import org.hibernate.Transaction; import java.io.Serializable; public class TestCustomEntities { private static final String TEST_FIELD_NAME = "email"; private static final String TEST_VALUE = "test@test.com"; public static void main(String[] args) { HibernateUtil.getInstance().getCurrentSession(); CustomizableEntityManager contactEntityManager = new CustomizableEntityManagerImpl(Contact.class); contactEntityManager.addCustomField(TEST_FIELD_NAME); Session session = HibernateUtil.getInstance().getCurrentSession(); Transaction tx = session.beginTransaction(); try { Contact contact = new Contact(); contact.setName("Contact Name 1"); contact.setValueOfCustomField(TEST_FIELD_NAME, TEST_VALUE); Serializable id = session.save(contact); tx.commit(); contact = (Contact) session.get(Contact.class, id); Object value = contact.getValueOfCustomField(TEST_FIELD_NAME); System.out.println("value = " + value); } catch (Exception e) { tx.rollback(); System.out.println("e = " + e); } } } |
清单19:测试创建自定义字段
这个类的main方法负责执行下面的工作:
1、创建Contact类的CustomizableEntityManager;
2、创建名为“email”的自定义字段;
3、在事务中,我们创建一个新的Contact对象,并设置自定义字段的值为“test@test.com”;
4、保存Contact;
5、获取自定义字段“email”的值。
我们可以看到执行的结果如下:
configuring Hibernate ... ok session opened. closing session ... ok closing session factory ... ok configuring Hibernate ... ok session opened. Hibernate: insert into tbl_contact (fld_name, fld_email) values (?, ?) value = test@test.com |