Hibernate и Oracle VARRAYS / NESTED TABLE - PullRequest
       31

Hibernate и Oracle VARRAYS / NESTED TABLE

4 голосов
/ 17 января 2011

Oracle поддерживает использование типов данных VARRAYS и NESTED TABLE, что позволяет использовать многозначные атрибуты. (http://www.orafaq.com/wiki/NESTED_TABLE)

В настоящее время я использую Hibernate 3 в качестве своей платформы ORM, но я не вижу, как я могу отобразить Hibernate на тип данных NESTED TABLE / VARRAY в моей базе данных.

Я смотрел на определение пользовательских типов в Hibernate, но безуспешно. (Может ли Hibernate обрабатывать ключевое слово Oracle «COLUMN_VALUE», необходимое для удаления вложенной таблицы?)

Кто-нибудь знает, как реализовать эти типы данных в Hibernate?

Спасибо всем за помощь.

- TBW.

Ответы [ 2 ]

3 голосов
/ 17 марта 2012

Тип пользователя Hibernate для таблицы чисел Oracle. 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 голос
/ 18 января 2011

Надеюсь, я ошибаюсь, и вы найдете лучший ответ в своем исследовании, но эта функция не поддерживается в 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. Смотрите этот пример работника: https://github.com/hibernate/hibernate-core/blob/master/hibernate-core/src/test/java/org/hibernate/test/jdbc/GeneralWorkTest.java

Тем не менее, я думаю, что вам нужно взвесить решения и пересмотреть, если вам действительно нужна вложенная таблица.

...