Warning: file_get_contents(/data/phpspider/zhask/data//catemap/9/java/308.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181

Warning: file_get_contents(/data/phpspider/zhask/data//catemap/1/hibernate/5.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
使用Hibernate从Postgres枚举到Java_Java_Hibernate_Jdbc_Types_Usertype - Fatal编程技术网

使用Hibernate从Postgres枚举到Java

使用Hibernate从Postgres枚举到Java,java,hibernate,jdbc,types,usertype,Java,Hibernate,Jdbc,Types,Usertype,我试图在数据库上创建一个枚举类型并将其转换为java,我编写了一个EnumUserType类来进行转换,但它无法识别PGobject类 public Object nullSafeGet(ResultSet rs, String[] names, SessionImplementor si, Object owner) throws HibernateException, SQLException { Object object = rs.getObject(names[

我试图在数据库上创建一个枚举类型并将其转换为java,我编写了一个EnumUserType类来进行转换,但它无法识别PGobject类

public Object nullSafeGet(ResultSet rs, String[] names, SessionImplementor si, Object owner)
        throws HibernateException, SQLException {
    Object object = rs.getObject(names[0]);
    if (rs.wasNull()) {
        return null;
    }

    if (object instanceof PGobject) {
        //code doesn't reach this line
    }

    log.info(object.getClass()); // prints class org.postgresql.util.PGobject
    return null;
}
我检查了,我有完全相同的postgresql驱动程序版本。 我看到了这个帖子:。这是一个我也会尝试的解决方案,但我的主要问题是:显然,它是同一个类,为什么它没有被承认为这样?我可以有两个不同的类,具有相同的名称和包吗?如果我仍然必须在Postgres中使用枚举,我如何修复它以正确映射到我的Java枚举

编辑:

我试着做一个:

PGobject pg = (PGobject) object;
它抛出一个类强制转换异常:

org.postgresql.util.PGobject cannot be cast to org.postgresql.util.PGobject

谢谢

我使用泛型类作为映射枚举的类型。然后,可以使用它映射所有枚举

课程内容如下:

public class GenericEnumUserType implements UserType, ParameterizedType {

private static final String DEFAULT_IDENTIFIER_METHOD_NAME = "name";
private static final String DEFAULT_VALUE_OF_METHOD_NAME = "valueOf";

private Class enumClass;
private Class identifierType;
private Method identifierMethod;
private Method valueOfMethod;
private NullableType type;
private int[] sqlTypes;

@Override
public void setParameterValues(Properties parameters) {
    String enumClassName = parameters.getProperty("enumClassName");
    try {
        enumClass = Class.forName(enumClassName).asSubclass(Enum.class);
    } catch (ClassNotFoundException cfne) {
        throw new HibernateException("Enum class not found", cfne);
    }

    String identifierMethodName = parameters.getProperty("identifierMethod", DEFAULT_IDENTIFIER_METHOD_NAME);

    try {
        identifierMethod = enumClass.getMethod(identifierMethodName, new Class[0]);
        identifierType = identifierMethod.getReturnType();
    } catch (Exception e) {
        throw new HibernateException("Failed to obtain identifier method", e);
    }

    type = (NullableType) TypeFactory.basic(identifierType.getName());

    if (type == null) {
        throw new HibernateException("Unsupported identifier type " + identifierType.getName());
    }

    sqlTypes = new int[] { type.sqlType() };

    String valueOfMethodName = parameters.getProperty("valueOfMethod", DEFAULT_VALUE_OF_METHOD_NAME);

    try {
        valueOfMethod = enumClass.getMethod(valueOfMethodName, new Class[] { identifierType });
    } catch (Exception e) {
        throw new HibernateException("Failed to obtain valueOf method", e);
    }
}

@Override
public Class returnedClass() {
    return enumClass;
}

@Override
public Object nullSafeGet(ResultSet rs, String[] names, Object owner) throws HibernateException, SQLException {
    Object identifier = type.get(rs, names[0]);
    if (rs.wasNull()) {
        return null;
    }

    try {
        return valueOfMethod.invoke(enumClass, new Object[] { identifier });
    } catch (Exception e) {
        throw new HibernateException("Exception while invoking " + "valueOf method " + valueOfMethod.getName()
                + " of enumeration class " + enumClass, e);
    }
}

@Override
public void nullSafeSet(PreparedStatement st, Object value, int index) throws HibernateException, SQLException {
    try {
        if (value == null) {
            st.setNull(index, type.sqlType());
        } else {
            Object identifier = identifierMethod.invoke(value, new Object[0]);
            type.set(st, identifier, index);
        }
    } catch (Exception e) {
        throw new HibernateException("Exception while invoking identifierMethod " + identifierMethod.getName()
                + " of enumeration class " + enumClass, e);
    }
}

@Override
public int[] sqlTypes() {
    return sqlTypes;
}

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

@Override
public Object deepCopy(Object value) throws HibernateException {
    return value;
}

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

@Override
public boolean equals(Object x, Object y) throws HibernateException {
    return x == y;
}

@Override
public int hashCode(Object x) throws HibernateException {
    return x.hashCode();
}

@Override
public boolean isMutable() {
    return false;
}

@Override
public Object replace(Object original, Object target, Object owner) throws HibernateException {
    return original;
}}
枚举类应如下所示:

public enum AccountStatus {
ACTIVE(1), BLOCKED(2), DELETED(3);

private AccountStatus(int id) {
    this.id = id;
}

private int id;

public int getId() {
    return id;
}

public void setId(int id) {
    this.id = id;
}

public static AccountStatus valueOf(int id) {
    switch (id) {
    case 1:
        return ACTIVE;
    case 2:
        return BLOCKED;
    case 3:
        return DELETED;
    default:
        throw new IllegalArgumentException();
    }
}}
<hibernate-mapping>
<typedef class="path.to.GenericEnumUserType" name="accountStatusType">
    <param name="enumClassName">com.systemonenoc.hermes.ratingengine.persistence.constants.AccountStatus</param>
    <param name="identifierMethod">getId</param>
</typedef>
<class name="package.to.class.with.enum.Account" table="account" schema="public">
    <property name="accountStatus" type="accountStatusType" column="account_status" not-null="true" />
[...]
</hibernate-mapping>
静态方法“valueOf”是将存储在数据库中的id转换为java对象所必需的

然后,hibernate映射如下所示:

public enum AccountStatus {
ACTIVE(1), BLOCKED(2), DELETED(3);

private AccountStatus(int id) {
    this.id = id;
}

private int id;

public int getId() {
    return id;
}

public void setId(int id) {
    this.id = id;
}

public static AccountStatus valueOf(int id) {
    switch (id) {
    case 1:
        return ACTIVE;
    case 2:
        return BLOCKED;
    case 3:
        return DELETED;
    default:
        throw new IllegalArgumentException();
    }
}}
<hibernate-mapping>
<typedef class="path.to.GenericEnumUserType" name="accountStatusType">
    <param name="enumClassName">com.systemonenoc.hermes.ratingengine.persistence.constants.AccountStatus</param>
    <param name="identifierMethod">getId</param>
</typedef>
<class name="package.to.class.with.enum.Account" table="account" schema="public">
    <property name="accountStatus" type="accountStatusType" column="account_status" not-null="true" />
[...]
</hibernate-mapping>

com.systemoneoc.hermes.ratingengine.persistence.constants.AccountStatus
盖蒂
[...]

因此,您必须使用typedef将类GenericEnumUserType声明为一个类型,并声明一个获取枚举id的方法(在本例中为getId())。在您的数据库中,id将作为值存储在整数列中,在java中,您将拥有enum对象。

为什么不使用
rs.getString()
?它应该以字符串形式返回枚举值,AFAIK。刚刚尝试了它,它抛出了一个异常:org.postgresql.util.PGobject不能转换为java.lang.StringObject忽略我之前的注释,缺少了其他内容。刚刚试过,效果不错,谢谢!这解决了我的问题,但我仍然对这个问题感到好奇。从异常情况来看,这看起来像是一个类加载器问题-由两个不同的类加载器加载的同一个类被java视为不同的类。我使用JBoss AS 7.1.1作为容器,我将同一个jar复制到jboss存储库和应用程序使用的本地maven存储库。