Oracle支持使用VARRAYS和NESTED TABLE数据类型,允许使用多值属性。 (http://www.orafaq.com/wiki/NESTED_TABLE)
我目前正在使用Hibernate 3作为我的ORM框架,但我无法看到如何将Hibernate映射到数据库中的NESTED TABLE / VARRAY数据类型。
我研究了在Hibernate中定义自定义类型,但没有成功。 (Hibernate甚至可以处理取消子表所需的“COLUMN_VALUE”Oracle关键字吗?)
有谁知道如何在Hibernate中实现这些数据类型?
谢谢大家的帮助。
- TBW。
答案 0 :(得分:3)
Hibernate用于Oracle的数字表的UserType。 在这里找到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);
}
}
答案 1 :(得分:1)
我希望我错了,你在研究中找到了更好的答案,但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)另一种选择是通过使用Hibernate worker直接使用JDBC。请参阅此工作人员的示例:https://github.com/hibernate/hibernate-core/blob/master/hibernate-core/src/test/java/org/hibernate/test/jdbc/GeneralWorkTest.java
那就是说,我认为如果你真的需要嵌套表,你必须加权解决方案并重新评估。