4

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

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

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

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

谢谢大家的帮助。

——待定。

4

2 回答 2

3

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);
}
}
于 2012-03-17T18:11:08.157 回答
1

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

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

1)实现你自己的用户类型。使用您的特定用户类型,您将有机会操作数据库提供的值(或即将发送到数据库的值)。但这只有在 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

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

于 2011-01-18T06:54:41.960 回答