1

我想实现以下工作流程:我在 postgresql 9 中设计表,我使用 Eclipse Indigo 中的 Hibernate 工具为这些表生成 POJO,并且我希望 Hibernate 使用注释。使用 Eclipse Indigo、最新的 Postgresql JDBC 驱动程序、Java 1.6 和来自 Eclipse 市场的 Hibernate 工具,这不起作用。

逆向工程向导将表的 UUID 字段视为 OTHER,并生成类型为 Serializable 的字段,而不是 UUID。插入 POJOS 抱怨试图将 bytea 数据插入 UUID 字段。简单地说:如何使用休眠工具对 POJOS 进行逆向工程,以便自动处理 UUID?

这是生成的字段:

私有可序列化实例 ID;

4

1 回答 1

2

自定义用户类型

您需要使用自定义用户类型来告诉 Hibernate 如何将 UUID 列序列化和反序列化为 java 对象。这是我的(使用 Hibernate 3.6.8.Final):

package your.package.usertype;

import java.io.Serializable;
import java.sql.PreparedStatement;
import java.sql.ResultSet;
import java.sql.SQLException;
import java.sql.Types;
import java.util.UUID;

import org.hibernate.HibernateException;
import org.hibernate.usertype.UserType;

public class UUIDType implements UserType {
    private final int[] sqlTypesSupported = new int[] { Types.NUMERIC };
    private final String CAST_EXCEPTION_TEXT = " cannot be cast to a java.util.UUID"; 

    public int[] sqlTypes() {
        return sqlTypesSupported;
    }

    @SuppressWarnings("rawtypes")
    public Class returnedClass() {
        return UUID.class;
    }

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

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

    public Object nullSafeGet(ResultSet rs, String[] names, Object owner) throws HibernateException, SQLException {
        assert(names.length == 1);
        Object value = rs.getObject(names[0]);
        if (value == null) {
            return null;
        }        

        UUID uuid = UUID.fromString( rs.getString( names[0] ) );
        return rs.wasNull() ? null : uuid;
    }

    public void nullSafeSet(PreparedStatement st, Object value, int index) throws HibernateException, SQLException {
        if (value == null) {
            st.setNull(index, Types.NULL);
            return;
        } 

        if (!UUID.class.isAssignableFrom(value.getClass())) {
            throw new HibernateException(value.getClass().toString() + CAST_EXCEPTION_TEXT);
        }        

        UUID uuid = (UUID) value;
        st.setObject(index, uuid, Types.OTHER);
    }

    public Object deepCopy(Object value) throws HibernateException {
        if (value == null)
            return null;
        UUID uuid = (UUID) value;
        return new UUID( uuid.getMostSignificantBits(), uuid.getLeastSignificantBits() );
    }

    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;
    }
}

休眠映射

您的 Hibernate 映射需要为 uuid 属性指定用户类型的类名:

<property name="uuid" type="your.package.usertype.UUIDType">
    <column name="uuid" not-null="true" />
</property>

逆向工程

由于您使用的是代码生成,因此您需要告诉逆向工程过程将这些列映射到您的自定义 UUIDType 用户类型。通过将所有 OTHER 类型映射到 UUIDType(未经测试),您应该能够在 hibernate.reveng.xml 文件中执行此操作:

<type-mapping>
    <sql-type jdbc-type="OTHER" hibernate-type="your.package.usertype.UUIDType" />
</type-mapping>

或通过指定特定的表/列:

<table name="your_table">
    <column name="uuid" type="your.package.usertype.UUIDType" />
</table>

或者,您可以通过创建自己的 ReverseEngineeringStrategy 类来更好地控制逆向工程过程,而不是使用 hibernate.reveng.xml:

package your.package.reveng;

import org.hibernate.cfg.reveng.DelegatingReverseEngineeringStrategy;
import org.hibernate.cfg.reveng.ReverseEngineeringStrategy;
import org.hibernate.cfg.reveng.TableIdentifier;

public class CustomReverseEngineeringStrategy extends DelegatingReverseEngineeringStrategy {
    public CustomReverseEngineeringStrategy( ReverseEngineeringStrategy delegate ){
        super(delegate);
    }

    public String columnToHibernateTypeName( TableIdentifier table, String columnName, int sqlType, int length, int precision, int scale, boolean nullable, boolean generatedIdentifier ){
        if( table.getName().equals("your_table") && columnName.equals("uuid") ){
            return "your.package.usertype.UUIDType";
        } else {
            return super.columnToHibernateTypeName( table, columnName, sqlType, length, precision, scale, nullable, generatedIdentifier );
        }
    }
}

编辑:看起来 org.hibernate.type.PostgresUUIDType 自 3.6.0.Beta1 以来就存在。您可能只能使用这种类型,但我认为您仍然必须在映射中指定它并直接进行逆向工程以将其用于所需的列。

于 2012-05-11T23:52:21.790 回答