使用Hibernate4处理Oracle XmlType字段类型

使用Hibernate4处理Oracle XmlType字段类型

网上有很多关于使用Hibernate处理Oracle XmlType的文章,但大多数资料都已经过时,不能使用。本人在经过对各种解决办法的测试汇总后,终于能够使用Hibernate4正常存取XmlType类型的字段了,而且解决4000个字符的限制。

使用的技术框架和环境:
- Hibernate 4.3.11
- Oracle 11g
- jdk 1.7


扩展Hibernate的UserType类型

请参考代码

添加Oracle的XmlType类型

import java.io.ByteArrayInputStream;
    import java.io.IOException;
    import java.io.Serializable;
    import java.io.StringWriter;
    import java.sql.Connection;
    import java.sql.PreparedStatement;
    import java.sql.ResultSet;
    import java.sql.SQLException;
    import javax.xml.parsers.DocumentBuilder;
    import javax.xml.parsers.DocumentBuilderFactory;
    import javax.xml.parsers.ParserConfigurationException;
    import javax.xml.transform.OutputKeys;
    import javax.xml.transform.Transformer;
    import javax.xml.transform.TransformerException;
    import javax.xml.transform.TransformerFactory;
    import javax.xml.transform.dom.DOMSource;
    import javax.xml.transform.stream.StreamResult;
    import oracle.xdb.XMLType;
    import org.hibernate.HibernateException;
    import org.hibernate.engine.spi.SessionImplementor;
    import org.hibernate.usertype.UserType;
    import org.w3c.dom.Document;
    import org.xml.sax.SAXException;

    public class OracleXmlType implements UserType, Serializable {

        private static final long serialVersionUID = 2308230823023l;
        private static final Class returnedClass = Document.class;
        private static final int[] SQL_TYPES = { oracle.xdb.XMLType._SQL_TYPECODE };

        public int[] sqlTypes() {
            return SQL_TYPES;
        }

        public Class returnedClass() {
            return returnedClass;
        }

        public int hashCode(Object _obj) {
            return _obj.hashCode();
        }

        public Object assemble(Serializable _cached, Object _owner)
                throws HibernateException {
            try {
                return OracleXmlType.stringToDom((String) _cached);
            } catch (Exception e) {
                throw new HibernateException(
                        "Could not assemble String to Document", e);
            }
        }

        public Serializable disassemble(Object _obj) throws HibernateException {
            try {
                return OracleXmlType.domToString((Document) _obj);
            } catch (Exception e) {
                throw new HibernateException(
                        "Could not disassemble Document to Serializable", e);
            }
        }

        public Object replace(Object _orig, Object _tar, Object _owner) {
            return deepCopy(_orig);
        }

        public boolean equals(Object arg0, Object arg1) throws HibernateException {
            if (arg0 == null && arg1 == null)
                return true;
            else if (arg0 == null && arg1 != null)
                return false;
            else
                return arg0.equals(arg1);
        }

        public Object deepCopy(Object value) throws HibernateException {
            if (value == null)
                return null;

            return (Document) ((Document) value).cloneNode(true);
        }

        public boolean isMutable() {
            return false;
        }

        protected static String domToString(Document _document)
                throws TransformerException {
            TransformerFactory tFactory = TransformerFactory.newInstance();
            Transformer transformer = tFactory.newTransformer();
            transformer.setOutputProperty(OutputKeys.INDENT, "yes");
            DOMSource source = new DOMSource(_document);
            StringWriter sw = new StringWriter();
            StreamResult result = new StreamResult(sw);
            transformer.transform(source, result);
            return sw.toString();
        }

        protected static Document stringToDom(String xmlSource)
                throws SAXException, ParserConfigurationException, IOException {
            DocumentBuilderFactory factory = DocumentBuilderFactory.newInstance();
            DocumentBuilder builder = factory.newDocumentBuilder();
            return builder.parse(new ByteArrayInputStream(xmlSource
                    .getBytes("UTF-8")));
        }

        @Override
        public Object nullSafeGet(ResultSet rs, String[] names,
                SessionImplementor arg2, Object arg3) throws HibernateException,
                SQLException {
            XMLType xmlType = (XMLType) rs.getObject(names[0]);
            return (xmlType != null) ? xmlType.getDOM() : null;
        }

        @Override
        public void nullSafeSet(PreparedStatement st, Object value, int index,
                SessionImplementor arg3) throws HibernateException, SQLException {
            OracleNativeExtractor extrator = new OracleNativeExtractor();
            Connection nativeConn = extrator
                    .getNativeConnection(st.getConnection());

            try {
                XMLType xmlType = null;
                if (value != null) {
                    xmlType = new oracle.xdb.XMLType(nativeConn,
                            OracleXmlType.domToString((Document) value));
                }
                st.setObject(index, xmlType);
            } catch (Exception e) {
                throw new SQLException(
                        "Could not covert Document to String for storage");
            }
        }
    }

添加处理Connection的类文件

import java.lang.reflect.Method;
    import java.sql.Connection;
    import java.sql.SQLException;

    import oracle.jdbc.driver.OracleConnection;
    import com.mchange.v2.c3p0.C3P0ProxyConnection;

    public class OracleNativeExtractor {

        public static Connection getRawConnection(Connection con) {
            return con;
        }

        public Connection getNativeConnection(Connection con) throws SQLException {
            if (con instanceof OracleConnection) {
                return con;
            }
            else if (con instanceof C3P0ProxyConnection) {
                C3P0ProxyConnection cpCon = (C3P0ProxyConnection) con;
                try {
                    Method rawConnMethod = getClass().getMethod("getRawConnection", 
                       new Class[] {Connection.class});
                    return (Connection) cpCon.rawConnectionOperation(
                            rawConnMethod, null, new Object[] {C3P0ProxyConnection.RAW_CONNECTION});
                }
                catch (SQLException ex) {
                    throw ex;
                }
                catch (Exception ex) {
                    throw new SQLException("Error in reflection:"+ex.getMessage());
                }
            }
            else {
                Connection conTmp = con.getMetaData().getConnection();
                if (conTmp instanceof OracleConnection) return conTmp;
            }

            throw new SQLException("Could not find Native Connection of type OracleConnection");
        }

    }

添加POJO Bean类,这里使用注解

import javax.persistence.Column;
    import javax.persistence.Entity;
    import javax.persistence.Id;
    import javax.persistence.Table;

    import org.hibernate.annotations.Type;
    import org.w3c.dom.Document;

    @Entity
    @Table(name = "TESTXML")
    public class Testxml implements java.io.Serializable {

        // Fields

        private String sid;
        private Document xmldata;

        // Constructors

        /** default constructor */
        public Testxml() {
        }

        /** minimal constructor */
        public Testxml(String sid) {
            this.sid = sid;
        }

        /** full constructor */
        public Testxml(String sid, Document xmldata) {
            this.sid = sid;
            this.xmldata = xmldata;
        }

        // Property accessors
        @Id
        @Column(name = "SID", unique = true, nullable = false, length = 50)
        public String getSid() {
            return this.sid;
        }

        public void setSid(String sid) {
            this.sid = sid;
        }

        @Type(type="OracleXmlType")
        @Column(name="XMLDATA", columnDefinition="XMLTYPE")
        public Document getXmldata() {
            return this.xmldata;
        }

        public void setXmldata(Document xmldata) {
            this.xmldata = xmldata;
        }

    }

使用到的其他库文件

程序运行中,需要使用到两个Oracle的类库:xdb6.jarxmlparserv2.jar,这两个文件可以在Oracle的安装目录中找到,建议不要从网上下载,网上下载的文件有些版本较旧,缺少方法体,本人就在这里踩了不少坑。

若有其他问题,欢迎交流,谢谢。

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值