iBatis开发详解(8)------------使用XML

  在实际应用中,很多时候我们使用到了XML格式的数据,比如FushionChart,iBatis允许使用XML作为数据库查询操作的参数,也允许数据库查询结果返回一个XML格式的数据。如果不是必须,使用XML并不会给带来什么价值,甚至不如直接使用POJO,因为它是强类型的。下面先来看看使用XML作为参数的情况,做参数时,可以使用String,也可以使用DOM来传递,此时的XML结构并不严格要求,只要格式良好即可。结合实例,比如有如下的XML片段: 
Xml代码   收藏代码
  1. <parameter><userId>1</userId></parameter>  

    这样,已映射的语句将获得名为userId的参数,且值为1,那么,我们来看看映射语句该怎么来写: 
Xml代码   收藏代码
  1. <select id="getUserByXMLId" parameterClass="xml" resultClass="User">  
  2.     select * from users where userId=#userId#  
  3. </select>  

    把parameterClass属性写成xml就行了,resultClass可以是你定义的Bean类型或Map,下面来看程序: 
Java代码   收藏代码
  1. String parameter = "<parameter><userId>1</userId></parameter>";  
  2. User user = (User) sqlMap.queryForObject("User.getUserByXMLId",  
  3.         parameter);  
  4. System.out.println(user);  

    这样就能得到结果了,这是String方式的XML传递,下面来看看DOM方式的写法,就需要使用到DOM生成的API了: 
Java代码   收藏代码
  1. public static void main(String[] args) throws SQLException,  
  2.             ParserConfigurationException {  
  3.     //创建XML文档  
  4.     org.w3c.dom.Document parameterDocument = DocumentBuilderFactory  
  5.             .newInstance().newDocumentBuilder().newDocument();  
  6.     //创建根元素  
  7.     org.w3c.dom.Element paramElement = parameterDocument  
  8.             .createElement("parameterDocument");  
  9.     //创建userId元素  
  10.     org.w3c.dom.Element userIdElement = parameterDocument  
  11. .createElement("userId");  
  12.     //设置userId元素的值  
  13.     userIdElement.setTextContent("1");  
  14.     //元素关系添加  
  15.     paramElement.appendChild(userIdElement);  
  16.     parameterDocument.appendChild(paramElement);  
  17.     //数据查询  
  18.     User user = (User) sqlMap.queryForObject("User.getUserByXMLId",  
  19.             parameterDocument);  
  20.     System.out.println(user);  
  21. }  

    这种方式就是DOM方式,代码比较复杂,但是结构很清晰。如果要引入第三方API,那么Dom4j是个不错的选择,写一个工具类来帮助我们简化开发,如下: 
Java代码   收藏代码
  1. package ibatis.util;  
  2. import java.io.IOException;  
  3. import org.dom4j.Document;  
  4. import org.dom4j.DocumentHelper;  
  5. import org.dom4j.Element;  
  6. /** 
  7.  * 使用dom4j生成XML工具类 
  8.  *  
  9.  * @author Sarin 
  10.  *  
  11.  */  
  12. public class XMLUtil {  
  13.     private Document document = null;  
  14.     public Document getDocument() {  
  15.         return document;  
  16.     }  
  17.     /** 
  18.      * 构造方法,初始化Document 
  19.      */  
  20.     public XMLUtil() {  
  21.         document = DocumentHelper.createDocument();  
  22.     }  
  23.     /** 
  24.      * 生成根节点 
  25.      *  
  26.      * @param rootName 
  27.      * @return 
  28.      */  
  29.     public Element addRoot(String rootName) {  
  30.         Element root = document.addElement(rootName);  
  31.         return root;  
  32.     }  
  33.     /** 
  34.      * 生成节点 
  35.      *  
  36.      * @param parentElement 
  37.      * @param elementName 
  38.      * @return 
  39.      */  
  40.     public Element addNode(Element parentElement, String elementName) {  
  41.         Element node = parentElement.addElement(elementName);  
  42.         return node;  
  43.     }  
  44.     /** 
  45.      * 为节点增加一个属性 
  46.      *  
  47.      * @param thisElement 
  48.      * @param attributeName 
  49.      * @param attributeValue 
  50.      */  
  51.     public void addAttribute(Element thisElement, String attributeName,  
  52.             String attributeValue) {  
  53.         thisElement.addAttribute(attributeName, attributeValue);  
  54.     }  
  55.     /** 
  56.      * 为节点增加多个属性 
  57.      *  
  58.      * @param thisElement 
  59.      * @param attributeNames 
  60.      * @param attributeValues 
  61.      */  
  62.     public void addAttributes(Element thisElement, String[] attributeNames,  
  63.             String[] attributeValues) {  
  64.         for (int i = 0; i < attributeNames.length; i++) {  
  65.             thisElement.addAttribute(attributeNames[i], attributeValues[i]);  
  66.         }  
  67.     }  
  68.     /** 
  69.      * 增加节点的值 
  70.      *  
  71.      * @param thisElement 
  72.      * @param text 
  73.      */  
  74.     public void addText(Element thisElement, String text) {  
  75.         thisElement.addText(text);  
  76.     }  
  77.     /** 
  78.      * 获取最终的XML 
  79.      *  
  80.      * @return 
  81.      * @throws IOException 
  82.      */  
  83.     public String getXML() {  
  84.         return document.asXML().substring(39);  
  85.     }  
  86. }  

    那么程序代码就简介很多了,如下: 
Java代码   收藏代码
  1. XMLUtil xmlParameter = new XMLUtil();  
  2. Element parameter = xmlParameter.addRoot("parameter");  
  3. Element userId = xmlParameter.addNode(parameter, "userId");  
  4. userId.addText("1");  
  5. System.out.println(xmlParameter.getXML());  
  6. User user = (User) sqlMap.queryForObject("User.getUserByXMLId",  
  7.         xmlParameter.getXML());  
  8. System.out.println(user);  

    XML参数就说到这里,下面来看看XML结果,由上面的示例不难得出,下面我们先来看一个简单示例: 
Xml代码   收藏代码
  1. <select id="getXMLValueByUserId" resultClass="xml" xmlResultName="User" parameterClass="int">  
  2.         select * from users where userId=#userId#  
  3. </select>  

    这是映射语句,很简单,参数都是见名知意了。xmlResultName参数的含义就是返回XML格式数据的跟元素名称,那么程序中可以这样来写: 
Java代码   收藏代码
  1. String xmlUser = (String) sqlMap.queryForObject(  
  2.         "User.getXMLValueByUserId"new Integer(1));  
  3. System.out.println(xmlUser);  

    我们得到如下结果(排版格式已经调整): 
Xml代码   收藏代码
  1. <?xml version="1.0" encoding="UTF-8" standalone="no"?>  
  2. <User>  
  3. <userId>1</userId>  
  4. <userName>Sarin</userName>  
  5. <password>123</password>  
  6. <age>23</age>  
  7. <mobile>15940912345</mobile>  
  8. <email>[email protected]</email>  
  9. </User>  

    这是获取一个结果的时候,那么如果要获取多条结果,XML结果会是什么样的呢?我们来看一下: 
Xml代码   收藏代码
  1. <select id="getUserXMLValue" resultClass="xml" xmlResultName="User">  
  2.     select * from users  
  3. </select>  

    程序也做相应的修改: 
Java代码   收藏代码
  1. List xmlUserList = sqlMap.queryForList("User.getUserXMLValue");  
  2. System.out.println(xmlUserList);  

    打印,得到集合形式的XML文档,每个元素都是独立的XML文档,这显然不是我们想要的形式,那么又该如何处理呢?把这些独立的XML手工拼接成一个XML文档,这显然不可取啊。要解决这个问题,就不能使用iBatis的XML结果了,返回Bean的集合,对Bean进行操作显然更为方法,下面给出一个简单的方法。 
    我们先来修改User类,加一个方法: 
Java代码   收藏代码
  1. public String toXML() {  
  2.     StringBuffer xmlValue = new StringBuffer();  
  3.     xmlValue.append("<user>");  
  4.     xmlValue.append("<userId>").append(getUserId()).append("</userId>");  
  5.     xmlValue.append("<userName>").append(getUserName()).append("</userName>");  
  6.     xmlValue.append("<password>").append(getPassword()).append("</password>");  
  7.     xmlValue.append("<mobile>").append(getMobile()).append("</mobile>");  
  8.     xmlValue.append("<email>").append(getEmail()).append("</email>");  
  9.     xmlValue.append("<age>").append(getAge()).append("</age>");  
  10.     xmlValue.append("</user>");  
  11.     return xmlValue.toString();  
  12. }  

    那么我们就可以这样来写程序了: 
Java代码   收藏代码
  1. List<User> userList = sqlMap.queryForList("User.getAllUsers");  
  2. StringBuffer xmlUserList = new StringBuffer("<users>");  
  3. for (User user : userList) {  
  4.     xmlUserList.append(user.toXML());  
  5. }  
  6. xmlUserList.append("</users>");  
  7. System.out.println(xmlUserList.toString());  

    这样我们就得到格式良好的XML文档了。下面给出一个工具类,利用反射将Bean中的属性转换为XML格式: 
Java代码   收藏代码
  1. package ibatis.util;  
  2. import java.beans.BeanInfo;  
  3. import java.beans.Introspector;  
  4. import java.beans.PropertyDescriptor;  
  5. import java.lang.reflect.Method;  
  6. public class BeanToXML {  
  7.     private Class beanClass;  
  8.     private BeanInfo beanInfo;  
  9.     private String name;  
  10.     public BeanToXML(Class beanClass, String name) throws Exception {  
  11.         this.beanClass = beanClass;  
  12.         this.name = name;  
  13.         beanInfo = Introspector.getBeanInfo(beanClass);  
  14.     }  
  15.     public String convertToXML(Object obj) throws Exception {  
  16.         StringBuffer xmlValue = new StringBuffer();  
  17.         if (obj.getClass().isAssignableFrom(beanClass)) {  
  18.             PropertyDescriptor[] pd = beanInfo.getPropertyDescriptors();  
  19.             if (pd.length > 0) {  
  20.                 xmlValue.append("<").append(name).append(">");  
  21.                 for (int i = 0; i < pd.length; i++) {  
  22.                     xmlValue.append(getProperty(obj, pd[i]));  
  23.                 }  
  24.                 xmlValue.append("</").append(name).append(">");  
  25.             } else {  
  26.                 xmlValue.append("<").append(name).append("/>");  
  27.             }  
  28.         } else {  
  29.             throw new ClassCastException("Class " + obj.getClass().getName()  
  30.                     + " is not compatible with " + beanClass.getName());  
  31.         }  
  32.         return xmlValue.toString();  
  33.     }  
  34.     private String getProperty(Object obj, PropertyDescriptor pd)  
  35.             throws Exception {  
  36.         StringBuffer propertyValue = new StringBuffer();  
  37.         Method method = pd.getReadMethod();  
  38.         Object bodyValue = method.invoke(obj);  
  39.         if (null == bodyValue) {            propertyValue.append("<").append(pd.getName()).append("/>");  
  40.         } else {            propertyValue.append("<").append(pd.getName()).append(">");  
  41.             propertyValue.append(bodyValue.toString());         propertyValue.append("</").append(pd.getName()).append(">");  
  42.         }  
  43.         return propertyValue.toString();  
  44.     }  
  45. }  

    而在测试程序中,这么写就行了: 
Java代码   收藏代码
  1. BeanToXML btx = new BeanToXML(User.class"user");  
  2. List<User> userList = sqlMap.queryForList("User.getAllUsers");  
  3. StringBuffer xmlUserList = new StringBuffer("<users>");  
  4. for (User user : userList) {  
  5.     xmlUserList.append(btx.convertToXML(user));  
  6. }  
  7. xmlUserList.append("</users>");  
  8. System.out.println(xmlUserList.toString());  

    也就得到了结果,只是在每个user元素中会多一个class子元素,如果不想要还要修改工具类。但这也并不是最佳实践,如果处理数据量太大,就要消耗大量的内存。 

你可能感兴趣的:(iBatis开发详解(8)------------使用XML)