iBatis開發(fā)詳解(8)---使用XML

2018-10-14 10:12 更新

   在實際應(yīng)用中,很多時候我們使用到了XML格式的數(shù)據(jù),比如FushionChart,iBatis允許使用XML作為數(shù)據(jù)庫查詢操作的參數(shù),也允許數(shù)據(jù)庫查詢結(jié)果返回一個XML格式的數(shù)據(jù)。如果不是必須,使用XML并不會給帶來什么價值,甚至不如直接使用POJO,因為它是強類型的。下面先來看看使用XML作為參數(shù)的情況,做參數(shù)時,可以使用String,也可以使用DOM來傳遞,此時的XML結(jié)構(gòu)并不嚴(yán)格要求,只要格式良好即可。結(jié)合實例,比如有如下的XML片段: 

<parameter><userId>1</userId></parameter>  
  這樣,已映射的語句將獲得名為userId的參數(shù),且值為1,那么,我們來看看映射語句該怎么來寫: 
<select id="getUserByXMLId" parameterClass="xml" resultClass="User">  
    select * from users where userId=#userId#  
</select>  

   把parameterClass屬性寫成xml就行了,resultClass可以是你定義的Bean類型或Map,下面來看程序:

String parameter = "<parameter><userId>1</userId></parameter>";  
User user = (User) sqlMap.queryForObject("User.getUserByXMLId",  
        parameter);  
System.out.println(user);  
  這樣就能得到結(jié)果了,這是String方式的XML傳遞,下面來看看DOM方式的寫法,就需要使用到DOM生成的API了:
public static void main(String[] args) throws SQLException,  
            ParserConfigurationException {  
    //創(chuàng)建XML文檔  
    org.w3c.dom.Document parameterDocument = DocumentBuilderFactory  
            .newInstance().newDocumentBuilder().newDocument();  
    //創(chuàng)建根元素  
    org.w3c.dom.Element paramElement = parameterDocument  
            .createElement("parameterDocument");  
    //創(chuàng)建userId元素  
    org.w3c.dom.Element userIdElement = parameterDocument  
.createElement("userId");  
    //設(shè)置userId元素的值  
    userIdElement.setTextContent("1");  
    //元素關(guān)系添加  
    paramElement.appendChild(userIdElement);  
    parameterDocument.appendChild(paramElement);  
    //數(shù)據(jù)查詢  
    User user = (User) sqlMap.queryForObject("User.getUserByXMLId",  
            parameterDocument);  
    System.out.println(user);  
}  
   這種方式就是DOM方式,代碼比較復(fù)雜,但是結(jié)構(gòu)很清晰。如果要引入第三方API,那么Dom4j是個不錯的選擇,寫一個工具類來幫助我們簡化開發(fā),如下: 
package ibatis.util;  
import java.io.IOException;  
import org.dom4j.Document;  
import org.dom4j.DocumentHelper;  
import org.dom4j.Element;  
/** 
 * 使用dom4j生成XML工具類 
 *  
 * @author Sarin 
 *  
 */  
public class XMLUtil {  
    private Document document = null;  
    public Document getDocument() {  
        return document;  
    }  
    /** 
     * 構(gòu)造方法,初始化Document 
     */  
    public XMLUtil() {  
        document = DocumentHelper.createDocument();  
    }  
    /** 
     * 生成根節(jié)點 
     *  
     * @param rootName 
     * @return 
     */  
    public Element addRoot(String rootName) {  
        Element root = document.addElement(rootName);  
        return root;  
    }  
    /** 
     * 生成節(jié)點 
     *  
     * @param parentElement 
     * @param elementName 
     * @return 
     */  
    public Element addNode(Element parentElement, String elementName) {  
        Element node = parentElement.addElement(elementName);  
        return node;  
    }  
    /** 
     * 為節(jié)點增加一個屬性 
     *  
     * @param thisElement 
     * @param attributeName 
     * @param attributeValue 
     */  
    public void addAttribute(Element thisElement, String attributeName,  
            String attributeValue) {  
        thisElement.addAttribute(attributeName, attributeValue);  
    }  
    /** 
     * 為節(jié)點增加多個屬性 
     *  
     * @param thisElement 
     * @param attributeNames 
     * @param attributeValues 
     */  
    public void addAttributes(Element thisElement, String[] attributeNames,  
            String[] attributeValues) {  
        for (int i = 0; i < attributeNames.length; i++) {  
            thisElement.addAttribute(attributeNames[i], attributeValues[i]);  
        }  
    }  
    /** 
     * 增加節(jié)點的值 
     *  
     * @param thisElement 
     * @param text 
     */  
    public void addText(Element thisElement, String text) {  
        thisElement.addText(text);  
    }  
    /** 
     * 獲取最終的XML 
     *  
     * @return 
     * @throws IOException 
     */  
    public String getXML() {  
        return document.asXML().substring(39);  
    }  
}  
   那么程序代碼就簡單很多了,如下: 
XMLUtil xmlParameter = new XMLUtil();  
Element parameter = xmlParameter.addRoot("parameter");  
Element userId = xmlParameter.addNode(parameter, "userId");  
userId.addText("1");  
System.out.println(xmlParameter.getXML());  
User user = (User) sqlMap.queryForObject("User.getUserByXMLId",  
        xmlParameter.getXML());  
System.out.println(user);  
   XML參數(shù)就說到這里,下面來看看XML結(jié)果,由上面的示例不難得出,下面我們先來看一個簡單示例: 
<select id="getXMLValueByUserId" resultClass="xml" xmlResultName="User" parameterClass="int">  
        select * from users where userId=#userId#  
</select>  
  這是映射語句,很簡單,參數(shù)都是見名知意了。xmlResultName參數(shù)的含義就是返回XML格式數(shù)據(jù)的跟元素名稱,那么程序中可以這樣來寫: 
String xmlUser = (String) sqlMap.queryForObject(  
        "User.getXMLValueByUserId", new Integer(1));  
System.out.println(xmlUser);  
  我們得到如下結(jié)果(排版格式已經(jīng)調(diào)整): 
<?xml version="1.0" encoding="UTF-8" standalone="no"?>  
<User>  
<userId>1</userId>  
<userName>Sarin</userName>  
<password>123</password>  
<age>23</age>  
<mobile>15940912345</mobile>  
<email>gmail@gmail.com</email>  
</User>  
  這是獲取一個結(jié)果的時候,那么如果要獲取多條結(jié)果,XML結(jié)果會是什么樣的呢?我們來看一下: 
<select id="getUserXMLValue" resultClass="xml" xmlResultName="User">  
    select * from users  
</select>  
   程序也做相應(yīng)的修改: 
List xmlUserList = sqlMap.queryForList("User.getUserXMLValue");  
System.out.println(xmlUserList);  
    打印,得到集合形式的XML文檔,每個元素都是獨立的XML文檔,這顯然不是我們想要的形式,那么又該如何處理呢?把這些獨立的XML手工拼接成一個XML文檔,這顯然不可取啊。要解決這個問題,就不能使用iBatis的XML結(jié)果了,返回Bean的集合,對Bean進(jìn)行操作顯然更為方法,下面給出一個簡單的方法。 

    我們先來修改User類,加一個方法: 
public String toXML() {  
    StringBuffer xmlValue = new StringBuffer();  
    xmlValue.append("<user>");  
    xmlValue.append("<userId>").append(getUserId()).append("</userId>");  
    xmlValue.append("<userName>").append(getUserName()).append("</userName>");  
    xmlValue.append("<password>").append(getPassword()).append("</password>");  
    xmlValue.append("<mobile>").append(getMobile()).append("</mobile>");  
    xmlValue.append("<email>").append(getEmail()).append("</email>");  
    xmlValue.append("<age>").append(getAge()).append("</age>");  
    xmlValue.append("</user>");  
    return xmlValue.toString();  
}  
   那么我們就可以這樣來寫程序了: 
List<User> userList = sqlMap.queryForList("User.getAllUsers");  
StringBuffer xmlUserList = new StringBuffer("<users>");  
for (User user : userList) {  
    xmlUserList.append(user.toXML());  
}  
xmlUserList.append("</users>");  
System.out.println(xmlUserList.toString());  
   這樣我們就得到格式良好的XML文檔了。下面給出一個工具類,利用反射將Bean中的屬性轉(zhuǎn)換為XML格式:
package ibatis.util;  
import java.beans.BeanInfo;  
import java.beans.Introspector;  
import java.beans.PropertyDescriptor;  
import java.lang.reflect.Method;  
public class BeanToXML {  
    private Class beanClass;  
    private BeanInfo beanInfo;  
    private String name;  
    public BeanToXML(Class beanClass, String name) throws Exception {  
        this.beanClass = beanClass;  
        this.name = name;  
        beanInfo = Introspector.getBeanInfo(beanClass);  
    }  
    public String convertToXML(Object obj) throws Exception {  
        StringBuffer xmlValue = new StringBuffer();  
        if (obj.getClass().isAssignableFrom(beanClass)) {  
            PropertyDescriptor[] pd = beanInfo.getPropertyDescriptors();  
            if (pd.length > 0) {  
                xmlValue.append("<").append(name).append(">");  
                for (int i = 0; i < pd.length; i++) {  
                    xmlValue.append(getProperty(obj, pd[i]));  
                }  
                xmlValue.append("</").append(name).append(">");  
            } else {  
                xmlValue.append("<").append(name).append("/>");  
            }  
        } else {  
            throw new ClassCastException("Class " + obj.getClass().getName()  
                    + " is not compatible with " + beanClass.getName());  
        }  
        return xmlValue.toString();  
    }  
    private String getProperty(Object obj, PropertyDescriptor pd)  
            throws Exception {  
        StringBuffer propertyValue = new StringBuffer();  
        Method method = pd.getReadMethod();  
        Object bodyValue = method.invoke(obj);  
        if (null == bodyValue) {            propertyValue.append("<").append(pd.getName()).append("/>");  
        } else {            propertyValue.append("<").append(pd.getName()).append(">");  
            propertyValue.append(bodyValue.toString());         propertyValue.append("</").append(pd.getName()).append(">");  
        }  
        return propertyValue.toString();  
    }  
}  
   而在測試程序中,這么寫就行了: 
BeanToXML btx = new BeanToXML(User.class, "user");  
List<User> userList = sqlMap.queryForList("User.getAllUsers");  
StringBuffer xmlUserList = new StringBuffer("<users>");  
for (User user : userList) {  
    xmlUserList.append(btx.convertToXML(user));  
}  
xmlUserList.append("</users>");  
System.out.println(xmlUserList.toString());  
   也就得到了結(jié)果,只是在每個user元素中會多一個class子元素,如果不想要還要修改工具類。但這也并不是最佳實踐,如果處理數(shù)據(jù)量太大,就要消耗大量的內(nèi)存。 

以上內(nèi)容是否對您有幫助:
在線筆記
App下載
App下載

掃描二維碼

下載編程獅App

公眾號
微信公眾號

編程獅公眾號