分類  >  Web前端 >

解決:Weblogic器皿、SSH框架下Hibernate映射Oracle XMLType方法與Jar包衝突

tags:    時間:2013-12-10 00:03:10
解決:Weblogic容器、SSH框架下Hibernate映射Oracle XMLType方法與Jar包衝突

雪影工作室版權所有,轉載請註明【http://blog.csdn.net/lina791211】


一、框架背景

      1、開發工具  MyEclipse 10 Pro

      2、框架使用 Struts2.3,Hibernate3,Spring3.0.5 (標準SSH框架)

      3、版本管理 svn 1.6 插件,visual svn 版本管理工具

      4、數 據  庫 Oracle 11g R2

二、Oracle XMLType

      引用Oracle官網對於Oracle的XMLType的部分解釋


      XMLType is a system-defined opaque type for handling XML data. It as predefined member functions on it to extract XML nodes and fragments.
      You can create columns of XMLType and insert XML documents into it. You can also generate XML documents as XMLType instances dynamically using the SYS_XMLGEN and SYS_XMLAGG SQL functions.



        Oracle XMLType的本質是blob類型,但是Oracle對其做了特殊處理,我們可以直接使用Xquery進行相關的創建、查詢、修改等操作,非常的利民。

三、Hibernate映射Oracle XMLType

      Hibernate可以映射Oracle 的 XMLType,默認的是String類型,也可以改成Text類型。

      如下所示,欄位STORAGE_DETAIL_XML是一個Oracle的XMLType類型欄位,Hibernate映射的時候自動映射成String

<?xml version="1.0" encoding="utf-8"?> <!DOCTYPE hibernate-mapping PUBLIC "-//Hibernate/Hibernate Mapping DTD 3.0//EN" "http://hibernate.sourceforge.net/hibernate-mapping-3.0.dtd"> <!--      Mapping file autogenerated by MyEclipse Persistence Tools --> <hibernate-mapping>     <class name="com.CDSS.main.model.DatasourceStorage" table="DATASOURCE_STORAGE" schema="DBCDSS">         <id name="storageId" type="java.lang.Long">             <column name="STORAGE_ID" precision="22" scale="0" />             <generator class="native">             	<param name="sequence">SEQUENCE_DSS</param>             </generator>         </id>         <property name="dsId" type="java.lang.Long">             <column name="DS_ID" precision="22" scale="0" />         </property>         <property name="storageDetailXml" type="java.lang.String">             <column name="STORAGE_DETAIL_XML" />         </property>         <property name="isReged" type="java.lang.String">             <column name="IS_REGED" />         </property>     </class> </hibernate-mapping> 

四、問題原由

      Hibernate可以映射Oracle 的 XMLType,默認的是String類型,其實正常情況下沒有多少問題,但是XMLType是一個繼承了blob的強大存在,應該可以存儲2G的數據,可以如果你按照clob來進行處理的話,Hibernate就會報錯。

      引用我在BBS上發布的問題貼,到現在還是沒有人能解決。(傷心中.....)


4.1、在使用 ***DAO.save(*) 或者 ***DAO.merge(*)的時候會出現問題。問題原因我也知道
4.2、當欄位dssXMLInfo的數據大小在4000字元以下的時候,可以正常保存或者merge
4.3、當欄位dssXMLInfo的數據超過4000字元的時候,直接報【Long列插入Long值】類似的錯誤
4.4、參考網上知道,當String的字元超過4000的時候,Hibernate會自動把String轉換成Long類型,網上的建議是把varchar改成clob或者blob【此法不通,不符合我的要求】
4.5、參考網上知道,Hibernate處理Oracle的xmlType的時候,多數自定義一個映射數據類型,然後把hibernate配置文件中的type="String" 換成對應的 type="類的包名"【參考URL:廣東精鷹軟體工作室(劉正仁)http://blog.csdn.net/wmbb/article/details/1045742】
    但是這個需要引入3個包,分別是xmlparserv2.jar 、xdb.jar和nls_charset12.jar,這三個包和我現有的weblogic自帶包、Java環境(使用Weblogic自帶的jdk1.6)發生衝突,啟動會報【XML解析錯】的錯誤。
    之前的項目中也使用這個方法解決問題的,但是部署系統的時候需要先把這幾個包刪除了才可以啟動,非常的不方便,而且操作十分麻煩。【故而放棄了】
4.6、今天又做了一次嘗試,直接使用sql語句,使用hibernate的sql數據提交。問題同樣也是字元超長,無法執行。【嘗試了一晚上,沒有成功,故而崩潰】


        上面描述的其實是一個問題,當數據超過4000字元的時候,直接報【Long列插入Long值】類似的錯誤。這個問題是Hibernate看見更新String類型數據,哇塞好大,那麼就給你轉成Long吧。很腦抽的現象.....糾結了好久。

五、解決方案

      Hibernate映射Oracle XMLType在網上有諸多版本,但是這些版本要不是Oracle版本較低(Oracle 9i),要不是Hibernate版本過高(Hibernate4),還有就是不是為Weblogic考慮的(使用jboss、tomcat等),因此拿過來很多東西都是錯誤的。


      參考網上諸多解決方案,經過好幾天的測試、處理,終於找打一個這中的解決方案,測試通過。(只針對第一章所講的環境,其它未測試)


5.1 系統添加幾個jar包

(1)ojdbc6_g.jar(從Oracle11g安裝目錄中找)【部署后刪除,weblogic自帶此包,項目中使用是因為需要相關的驅動】

(2)xmlparserv2.jar(從Oracle11g安裝目錄中找)【部署后刪除,此文件和其它jar衝突,原因未知,啟動成功后建議還原

(3)xdb.jar(從網上下載)

(4)weblogic.jar(從weblogic安裝路徑下找)【部署后刪除,weblogic自帶此包,項目中使用是因為需要相關的驅動】


5.2 新建自定義的OracleType,繼承UserType, Serializable。

package com.***.util.XMLHandle;  import java.io.Serializable; import java.sql.Connection; import java.sql.PreparedStatement; import java.sql.ResultSet; import java.sql.SQLException;  import oracle.sql.OPAQUE; import oracle.xdb.XMLType;  import org.hibernate.HibernateException; import org.hibernate.usertype.UserType;  import weblogic.jdbc.wrapper.PoolConnection;  @SuppressWarnings("rawtypes") public class OracleXMLType implements UserType, Serializable { 	/** 	 *  	 */ 	private static final long serialVersionUID = 1L; 	private static final Class returnedClass = String.class; 	private static final int[] SQL_TYPES = new int[] { oracle.xdb.XMLType._SQL_TYPECODE };  	public int[] sqlTypes() { 		return SQL_TYPES; 	}  	public Class returnedClass() { 		return returnedClass; 	}  	public boolean equals(Object arg0, Object arg1) throws HibernateException { 		if (arg0 == null || arg1 == null) { 			throw new HibernateException("None of the arguments can be null."); 		} 		if (arg0 instanceof oracle.xdb.XMLType 				&& arg1 instanceof oracle.xdb.XMLType) { 			return arg0.equals(arg1); 		} 		return false; 	}  	public int hashCode(Object arg0) throws HibernateException { 		return 0; 	}  	public Object nullSafeGet(ResultSet rs, String[] names, Object arg2) 			throws HibernateException, SQLException {  		OPAQUE op = (OPAQUE) rs.getObject(names[0]); 		oracle.xdb.XMLType xt = oracle.xdb.XMLType.createXML(op); 		return xt.getStringVal(); 	}  	public void nullSafeSet(PreparedStatement st, Object value, int index) 			throws HibernateException, SQLException {  		Connection conn = ((PoolConnection) st.getConnection()) 				.getVendorConnection();  		OPAQUE aClob = XMLType.createXML(conn, (String) value); 	//	XMLType aClob = XMLType.createXML(conn, (String) value); 		st.setObject(index, aClob);  	}  	public Object deepCopy(Object value) throws HibernateException { 		return value; 	}  	public boolean isMutable() { 		return false; 	}  	public Serializable disassemble(Object arg0) throws HibernateException { 		return null; 	}  	public Object assemble(Serializable arg0, Object arg1) 			throws HibernateException { 		return null; 	}  	public Object replace(Object arg0, Object arg1, Object arg2) 			throws HibernateException { 		return null; 	} } 

5.3 修改Hibernate映射文件,把type="string"換成type="com.CDSS.util.XMLHandle.OracleXMLType"【你定義的類】

<?xml version="1.0" encoding="utf-8"?> <!DOCTYPE hibernate-mapping PUBLIC "-//Hibernate/Hibernate Mapping DTD 3.0//EN" "http://hibernate.sourceforge.net/hibernate-mapping-3.0.dtd"> <!--      Mapping file autogenerated by MyEclipse Persistence Tools --> <hibernate-mapping>     <class name="com.CDSS.main.model.DatasourceStorage" table="DATASOURCE_STORAGE" schema="DBCDSS">         <id name="storageId" type="java.lang.Long">             <column name="STORAGE_ID" precision="22" scale="0" />             <generator class="native">             	<param name="sequence">SEQUENCE_DSS</param>             </generator>         </id>         <property name="dsId" type="java.lang.Long">             <column name="DS_ID" precision="22" scale="0" />         </property>         <property name="storageDetailXml" type="com.CDSS.util.XMLHandle.OracleXMLType">             <column name="STORAGE_DETAIL_XML" />         </property>         <property name="isReged" type="java.lang.String">             <column name="IS_REGED" />         </property>     </class> </hibernate-mapping> 
5.4、其它不變,然後部署,啟動之前刪除前面提到的衝突包。此時就可以直接使用Hibernate自帶的Merge或者save或者update進行更新數據超過4000的信息了。

六、后感

      Hibernate還是需要繼續努力的!


推薦閱讀文章

Bookmark the permalink ,來源:互聯網