【问题标题】:Hibernate and Oracle VARRAYS/NESTED TABLEHibernate 和 Oracle VARRAYS/嵌套表
【发布时间】:2011-06-10 09:34:54
【问题描述】:

Oracle 支持使用 VARRAYS 和 NESTED TABLE 数据类型,允许使用多值属性。 (http://www.orafaq.com/wiki/NESTED_TABLE)

我目前使用 Hibernate 3 作为我的 ORM 框架,但我看不到如何将 Hibernate 映射到我的数据库中的 NESTED TABLE/VARRAY 数据类型。

我查看了在 Hibernate 中定义自定义类型,但没有成功。 (Hibernate 甚至可以处理取消嵌套子表所需的“COLUMN_VALUE”Oracle 关键字吗?)

有谁知道如何在 Hibernate 中实现这些数据类型?

感谢大家的帮助。

-- 待定。

【问题讨论】:

    标签: java oracle hibernate varray nested-table


    【解决方案1】:

    Oracle 数字表的 Hibernate 用户类型。 OracleNativeExtractor 在这里找到:https://community.jboss.org/wiki/MappingOracleXmlTypeToDocument。字符串 YOUR_CUSTOM_ARRAY_TYPE 替换为您的姓名。

    import oracle.sql.ARRAY;
    import oracle.sql.ArrayDescriptor;
    import org.apache.commons.lang.ArrayUtils;
    import org.hibernate.HibernateException;
    import org.hibernate.usertype.UserType;
    
    import java.io.Serializable;
    import java.sql.*;
    import java.util.ArrayList;
    import java.util.Arrays;
    import java.util.List;    
    
    public class ArrayUserType
        implements UserType, Serializable {
    
    private static final OracleNativeExtractor EXTRACTOR = new OracleNativeExtractor();
    
    @Override
    public int[] sqlTypes() {
        return new int[]{Types.ARRAY};
    }
    
    @Override
    public Class returnedClass() {
        return List.class;
    }
    
    @Override
    public boolean equals(Object x, Object y) throws HibernateException {
        if (x == null && y == null) return true;
        else if (x == null && y != null) return false;
        else return x.equals(y);
    }
    
    @Override
    public int hashCode(Object x) throws HibernateException {
        return x.hashCode();
    }
    
    @Override
    public Object nullSafeGet(ResultSet rs, String[] names, Object owner) throws HibernateException, SQLException {
        return Arrays.asList(ArrayUtils.toObject(((ARRAY) rs.getObject(names[0])).getLongArray()));
    }
    
    @Override
    public void nullSafeSet(PreparedStatement st, Object value, int index) throws HibernateException, SQLException {
        ARRAY array = null;
        if (value != null) {
            Connection nativeConn = EXTRACTOR.getNativeConnection(st.getConnection());
            ArrayDescriptor descriptor =
                    ArrayDescriptor.createDescriptor("YOUR_CUSTOM_ARRAY_TYPE", nativeConn);
            array = new ARRAY(descriptor, nativeConn, ((List<Long>) value).toArray(new Long[]{}));
        }
    
        st.setObject(1, array);
    }
    
    @Override
    public Object deepCopy(Object value) throws HibernateException {
        if (value == null) return null;
    
        return new ArrayList<Long>((List<Long>) value);
    }
    
    @Override
    public boolean isMutable() {
        return false;
    }
    
    public Object assemble(Serializable _cached, Object _owner)
            throws HibernateException {
        return _cached;
    }
    
    public Serializable disassemble(Object _obj)
            throws HibernateException {
        return (Serializable) _obj;
    }
    
    @Override
    public Object replace(Object original, Object target, Object owner) throws HibernateException {
        return deepCopy(original);
    }
    }
    

    【讨论】:

    • 就这样?我们需要在休眠实体中映射它吗?这个类怎么用?
    • 是的,您需要将其映射到您的实体中。如果您使用休眠注释,请将 @Type(type="mypackage.ArrayUserType") 添加到您的字段中。
    【解决方案2】:

    我希望我错了,希望您在研究中找到更好的答案,但 Hibernate 不支持此功能。 Hibernate 依赖于标准 JDBC 与数据库通信,这些特性不是标准的一部分。它们是 Oracle 扩展。

    也就是说,我可以想到一些解决方法:

    1) 实现您自己的 UserType。使用您的特定用户类型,您将有机会操作数据库提供的值(或即将发送到数据库)。但这只有在 Oracle 将此值作为以下 java.sql.Types 之一提供时才有效:http://download.oracle.com/javase/1.5.0/docs/api/java/sql/Types.html

    2) 另一种选择是直接使用 JDBC,通过使用 Hibernate worker。请参阅以下 Worker 示例:https://github.com/hibernate/hibernate-core/blob/master/hibernate-core/src/test/java/org/hibernate/test/jdbc/GeneralWorkTest.java

    也就是说,我认为您必须权衡解决方案并重新评估您是否真的需要嵌套表。

    【讨论】:

    • 是的,Hibernate 不能支持所有供应商特定的扩展。我们有一个 DAO 对象,它可以保护上层免受此类 Oracle 类型的影响,因此我们将来可能会更改实现。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2016-08-07
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2021-11-17
    相关资源
    最近更新 更多