基于不同版本Hibernate的OracleXmlType处理详解编程语言

需求

需要从Oracle数据库中查出xmltype类型的数据,并且与pojo类中的org.w3c.dom.Document类型的字段对应。由于Hibernate4(4.3.11.Final)和Hibernate5(5.3.7.Final)对于org.hibernate.usertype.UserType接口的nullSafeGet和nullSafeSet方法的形参定义不同,所以在Hibernate4和Hibernate5下对应Oracle的xmltype数据的OracleXmlType类的定义也不同。

Hibernate4项目

DatDocument.java

package com.jake.hib4.pojo; 
 
import lombok.Data; 
import org.hibernate.annotations.Type; 
import org.w3c.dom.Document; 
 
import javax.persistence.*; 
 
@Data 
@Entity 
@Table(name = "DAT_DOCUMENT") 
public class DatDocument { 
 
    @Id 
    @Column(name = "APP_ID", unique = true, nullable = false, length = 100) 
    private String datDocumentId; 
 
    @Type(type = "com.jake.hib4.hiextype.OracleXmlType") 
    @Column(name = "DOCUMENT_DATA", columnDefinition = "XMLTYPE") 
    private Document document; 
 
} 
 

在Hibernate4的项目中对于OracleXmlType的定义如下:
OracleXmlType.java

// 
// Source code recreated from a .class file by IntelliJ IDEA 
// (powered by Fernflower decompiler) 
// 
 
package com.jake.hib4.hiextype; 
 
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.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.apache.commons.lang3.StringUtils; 
import org.hibernate.HibernateException; 
import org.hibernate.engine.spi.SessionImplementor; 
import org.hibernate.usertype.UserType; 
import org.slf4j.Logger; 
import org.slf4j.LoggerFactory; 
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 = new int[]{2007}; 
    private static final Logger LOG = LoggerFactory.getLogger(OracleXmlType.class); 
 
    public OracleXmlType() { 
    } 
 
    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 stringToDom((String)_cached); 
        } catch (Exception var4) { 
            throw new HibernateException("Could not assemble String to Document", var4); 
        } 
    } 
 
    public Serializable disassemble(Object _obj) throws HibernateException { 
        try { 
            return domToString((Document)_obj); 
        } catch (Exception var3) { 
            throw new HibernateException("Could not disassemble Document to Serializable", var3); 
        } 
    } 
 
    public Object replace(Object _orig, Object _tar, Object _owner) { 
        return this.deepCopy(_orig); 
    } 
 
    public boolean equals(Object arg0, Object arg1) throws HibernateException { 
        if (arg0 == null && arg1 == null) { 
            return true; 
        } else { 
            return arg0 == null && arg1 != null ? false : arg0.equals(arg1); 
        } 
    } 
 
    public Object deepCopy(Object value) throws HibernateException { 
        return value == null ? null : (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("indent", "yes"); 
        if (_document == null) { 
            return "<root></root>"; 
        } else { 
            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(); 
        if (StringUtils.isBlank(xmlSource)) { 
            xmlSource = "<root></root>"; 
        } 
 
        return builder.parse(new ByteArrayInputStream(xmlSource.getBytes("UTF-8"))); 
    } 
 
    public Object nullSafeGet(ResultSet rs, String[] names, SessionImplementor arg2, Object arg3) throws HibernateException, SQLException { 
        XMLType xmlType = null; 
 
        try { 
            xmlType = (XMLType)rs.getObject(names[0]); 
        } catch (Exception var7) { 
            LOG.error("Hibernate get XMLType Data Error!", var7); 
        } 
 
        return xmlType != null ? xmlType.getDOM() : null; 
    } 
 
    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 XMLType(nativeConn, domToString((Document)value)); 
            } 
 
            st.setObject(index, xmlType); 
        } catch (Exception var8) { 
            throw new SQLException("Could not covert Document to String for storage"); 
        } 
    } 
} 
 

Hibernate5项目

DatDocument.java

package com.jake.hib5.pojo; 
 
import lombok.Data; 
import org.hibernate.annotations.Type; 
import org.w3c.dom.Document; 
 
import javax.persistence.Column; 
import javax.persistence.Entity; 
import javax.persistence.Id; 
import javax.persistence.Table; 
 
@Data 
@Entity 
@Table(name = "DAT_DOCUMENT") 
public class DatDocument { 
 
    @Id 
    @Column(name = "APP_ID", unique = true, nullable = false, length = 100) 
    private String datDocumentId; 
 
    @Type(type = "com.jake.hib5.type.OracleXmlType") 
    @Column(name = "DOCUMENT_DATA", columnDefinition = "XMLTYPE") 
    private Document document; 
 
} 
 

OracleXmlType.java

package com.jake.hib5.type; 
 
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.Transformer; 
import javax.xml.transform.TransformerException; 
import javax.xml.transform.TransformerFactory; 
import javax.xml.transform.dom.DOMSource; 
import javax.xml.transform.stream.StreamResult; 
 
import com.gzsolartech.smartforms.hiextype.OracleNativeExtractor; 
import oracle.xdb.XMLType; 
import org.apache.commons.lang3.StringUtils; 
import org.hibernate.HibernateException; 
import org.hibernate.engine.spi.SharedSessionContractImplementor; 
import org.hibernate.usertype.UserType; 
import org.slf4j.Logger; 
import org.slf4j.LoggerFactory; 
import org.w3c.dom.Document; 
import org.xml.sax.SAXException; 
 
/** 
 * [email protected] 
 * [email protected],但该类实现的UserType接口来自Hibernate4, 
 * 其nullSafeGet和nullSafeSet方法的第三个参数与Hibernate5不同:Hibernate4为SessionImplementor, 
 * Hibernate5为SharedSessionContractImplementor,Postman访问时会报AbstractMethodError:nullSafeGet/nullSafeSet。 
 * 所以,解决方法就是重写OracleXmlType类,实现Hibernate5的UserType接口。 
 */ 
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 = new int[]{2007}; 
    private static final Logger LOG = LoggerFactory.getLogger(OracleXmlType.class); 
 
    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 stringToDom((String)_cached); 
        } catch (Exception var4) { 
            throw new HibernateException("Could not assemble String to Document", var4); 
        } 
    } 
 
    public Serializable disassemble(Object _obj) throws HibernateException { 
        try { 
            return domToString((Document)_obj); 
        } catch (Exception var3) { 
            throw new HibernateException("Could not disassemble Document to Serializable", var3); 
        } 
    } 
 
    public Object replace(Object _orig, Object _tar, Object _owner) { 
        return this.deepCopy(_orig); 
    } 
 
    public boolean equals(Object arg0, Object arg1) throws HibernateException { 
        if (arg0 == null && arg1 == null) { 
            return true; 
        } else { 
            return arg0 == null && arg1 != null ? false : arg0.equals(arg1); 
        } 
    } 
 
    public Object deepCopy(Object value) throws HibernateException { 
        return value == null ? null : (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("indent", "yes"); 
        if (_document == null) { 
            return "<root></root>"; 
        } else { 
            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(); 
        if (StringUtils.isBlank(xmlSource)) { 
            xmlSource = "<root></root>"; 
        } 
 
        return builder.parse(new ByteArrayInputStream(xmlSource.getBytes("UTF-8"))); 
    } 
 
    public Object nullSafeGet(ResultSet rs, String[] names, SharedSessionContractImplementor arg2, Object arg3) throws HibernateException, SQLException { 
        XMLType xmlType = null; 
 
        try { 
            xmlType = (XMLType)rs.getObject(names[0]); 
        } catch (Exception var7) { 
            LOG.error("Hibernate get XMLType Data Error!", var7); 
        } 
 
        return xmlType != null ? xmlType.getDOM() : null; 
    } 
 
    public void nullSafeSet(PreparedStatement st, Object value, int index, SharedSessionContractImplementor arg3) throws HibernateException, SQLException { 
        OracleNativeExtractor extractor = new OracleNativeExtractor(); 
        Connection nativeConn = extractor.getNativeConnection(st.getConnection()); 
 
        try { 
            XMLType xmlType = null; 
            if (value != null) { 
                xmlType = new XMLType(nativeConn, domToString((Document)value)); 
            } 
 
            st.setObject(index, xmlType); 
        } catch (Exception var8) { 
            throw new SQLException("Could not covert Document to String for storage"); 
        } 
    } 
} 
 

原创文章,作者:奋斗,如若转载,请注明出处:https://blog.ytso.com/19598.html

(0)
上一篇 2021年7月19日
下一篇 2021年7月19日

相关推荐

发表回复

登录后才能评论