如何配置hibernate方言以支持多种数组类型?

时间:2018-04-21 14:29:01

标签: hibernate

我有一个返回sql数组的本机查询:

select person.id as personid, array_agg(car.model) as personscarsmodels
from person join car on person.id = car.ownerpersonid
group by person.id

为了在hibernate中添加对sql数组的支持,我添加到pom.xml:

    <dependency>
        <groupId>com.vladmihalcea</groupId>
        <artifactId>hibernate-types-52</artifactId>
        <version>2.2.0</version>
    </dependency>

当我配置我的自定义方言时,Hibernate将正确返回一个字符串数组:

public class CustomPostgreSQLDialect extends PostgreSQL95Dialect {

    public CustomPostgreSQLDialect() {
        super();
        registerHibernateType(Types.ARRAY, "string-array"); 
    }

    @Override
    public void contributeTypes(TypeContributions typeContributions, ServiceRegistry serviceRegistry) {
        super.contributeTypes(typeContributions, serviceRegistry);

        typeContributions.contributeType(StringArrayType.INSTANCE);
    }
}

问题是如何添加对两个字符串和int数组的支持,以便我可以添加类似的查询,但现在使用int数组。如果我像这样配置方言:

public class CustomPostgreSQLDialect extends PostgreSQL95Dialect {

    public CustomPostgreSQLDialect() {
        super();
        registerHibernateType(Types.ARRAY, "string-array");
        registerHibernateType(Types.ARRAY, "int-array");
    }

    @Override
    public void contributeTypes(TypeContributions typeContributions, ServiceRegistry serviceRegistry) {
        super.contributeTypes(typeContributions, serviceRegistry);

        typeContributions.contributeType(StringArrayType.INSTANCE);
        typeContributions.contributeType(IntArrayType.INSTANCE);
    }
}

抛出此异常:

java.lang.ClassCastException: java.lang.String cannot be cast to java.lang.Integer

2 个答案:

答案 0 :(得分:0)

当你这样做时:

registerHibernateType(Types.ARRAY, "string-array");
registerHibernateType(Types.ARRAY, "int-array");

第二个电话实际上覆盖了第二个电话。这就是你得到错误的原因。

您只能将JDBC Type注册到单个Hibernate Type。因此,在您的情况下,您可以使用通用的Object[]类型。

答案 1 :(得分:0)

另一种可能性是为数组定义自定义UserType,而不是使用hibernate-types-52 jar:

public class ArrayUserType implements UserType {

    public static final String HIBERNATE_TYPE_NAME = "arrayusertype";
    public static final ArrayUserType INSTANCE = new ArrayUserType();

    public int[] sqlTypes() {
        return new int[] { Types.ARRAY };
    }

    public Class<List> returnedClass() {
        return List.class;
    }

    public boolean equals(Object x, Object y) throws HibernateException {
        return x == null ? y == null : x.equals(y);
    }

    public int hashCode(Object x) throws HibernateException {
        return x == null ? 0 : x.hashCode();
    }

    @Override
    public Object nullSafeGet(ResultSet rs, String[] names, SharedSessionContractImplementor session, Object owner) throws HibernateException, SQLException {

        if (names != null && names.length > 0 && rs != null && rs.getArray(names[0]) != null) {

            Object[] array = (Object[]) rs.getArray(names[0]).getArray();

            List list = new ArrayList();
            for (Object element : array) {
                list.add(element);
            }

            return list;
        }

        return null;
    }

    @Override
    public void nullSafeSet(PreparedStatement st, Object value, int index, SharedSessionContractImplementor session) throws HibernateException, SQLException {
        // does not seem to be needed just for getting an array from db
        throw new UnsupportedOperationException();
    }

    public Object deepCopy(Object value) throws HibernateException {
        // does not seem to be needed just for getting an array from db
        throw new UnsupportedOperationException();
    }

    public boolean isMutable() {
        return false;
    }

    public Serializable disassemble(Object value) throws HibernateException {
        return (Serializable) value;
    }

    public Object assemble(Serializable cached, Object owner) throws HibernateException {
        return cached;
    }

    public Object replace(Object original, Object target, Object owner) throws HibernateException {
        return original;
    }
}

并以新的自定义方言注册:

    public class CustomPostgreSQLDialect extends PostgreSQL95Dialect {

        public CustomPostgreSQLDialect() {
            super();
            registerHibernateType(Types.ARRAY, ArrayUserType.HIBERNATE_TYPE_NAME);
        }

        @Override
        public void contributeTypes(TypeContributions typeContributions, ServiceRegistry serviceRegistry) {
            super.contributeTypes(typeContributions, serviceRegistry);

            typeContributions.contributeType(ArrayUserType.INSTANCE, ArrayUserType.HIBERNATE_TYPE_NAME);
        }
    }