[英]Enum from Postgres to Java using Hibernate
I'm trying to have a enum type on the database and convert it to java, I wrote a EnumUserType class to do the conversion, but it doesn't recognize the PGobject class. 我试图在数据库上使用一个枚举类型并将其转换为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;
}
I checked and I have the exact same postgresql driver version. 我检查了一下,然后找到了完全相同的postgresql驱动程序版本。 I saw this post: Java enum with Eclipselink . 我看到了这篇文章: Eclipselink的Java枚举 。 It is a solution that I will also try, but my main question is: apparently it is the same class, why it is not being recognized as such? 我也将尝试这种解决方案,但是我的主要问题是:显然它是同一个类,为什么不能这样识别它? Can I have two different classes with the same name and package? 我可以使用名称和软件包相同的两个不同的类吗? If I still have to use enums in Postgres, how can I fix it to properly map to my Java enum? 如果仍然需要在Postgres中使用枚举,如何解决它以正确映射到Java枚举?
EDIT: 编辑:
I tried to do a: 我试图做一个:
PGobject pg = (PGobject) object;
and it throws a class cast exception: 并引发类强制转换异常:
org.postgresql.util.PGobject cannot be cast to org.postgresql.util.PGobject
Thanks 谢谢
I use a generic class to use as a type to map a enum. 我使用泛型类作为映射枚举的类型。 Then, you can map all your enums using it. 然后,您可以使用它映射所有枚举。
The class is this: 该类是这样的:
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;
}}
Enum class should be like this: 枚举类应如下所示:
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();
}
}}
The static method "valueOf" is necessary to convert from id stored in database to java object. 静态方法“ valueOf”是将数据库中存储的id转换为java对象所必需的。
Then, hibernate mapping is like this: 然后,休眠映射如下所示:
<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>
So you have to declare as a type the class GenericEnumUserType with typedef, and a method to get the id of the enum (in this case, getId()). 因此,您必须将具有typedef的GenericEnumUserType类声明为类型,并声明一个用于获取枚举ID(在本例中为getId())的方法。 In your database wil be store the id as value in a integer column, and in java you will have the enum object. 在您的数据库中,将id作为值存储在整数列中,而在java中,您将拥有enum对象。
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.