我们将枚举保留为字符串。用于@Enumerated(EnumType.STRING)
使用字符串表示(而不是自动枚举代码)。这使您在数据库中的数据更具可读性。
如果您确实需要将枚举映射到特殊代码(遗留代码等),则需要自定义映射。首先是一个将枚举映射到数据库并返回的基类:
import java.io.Serializable;
import org.hibernate.Hibernate;
import org.hibernate.HibernateException;
import org.hibernate.usertype.UserType;
public abstract class CustomEnumType implements UserType
{
public Object deepCopy (Object value) throws HibernateException
{
return value;
}
public Serializable disassemble (Object value) throws HibernateException
{
return (Serializable)value;
}
public Object assemble (Serializable cached, Object owner)
throws HibernateException
{
return cached;
}
public boolean equals (Object x, Object y) throws HibernateException
{
// Correct for Enums
return x == y;
}
public int hashCode (Object x) throws HibernateException
{
return x.hashCode ();
}
public boolean isMutable ()
{
return false;
}
public Object replace (Object original, Object target, Object owner)
throws HibernateException
{
return original;
}
public int[] sqlTypes ()
{
return new int[]{ Hibernate.STRING.sqlType() };
}
}
现在是一个扩展,它使用 DBEnum 将您的枚举值映射到数据库并返回:
import java.sql.PreparedStatement;
import java.sql.ResultSet;
import java.sql.SQLException;
import org.hibernate.Hibernate;
import org.hibernate.HibernateException;
import org.apache.log4j.Logger;
public abstract class DBEnumType extends CustomEnumType
{
private final static Logger log = Logger.getLogger(DBEnumType.class);
private static final boolean IS_VALUE_TRACING_ENABLED = log.isTraceEnabled();
public Object nullSafeGet (ResultSet rs, String[] names, Object owner)
throws HibernateException, SQLException
{
String value = rs.getString (names[0]);
if (rs.wasNull ())
return null;
return toEnum (value);
}
public abstract Object toEnum (String value);
public void nullSafeSet (PreparedStatement st, Object value, int index)
throws HibernateException, SQLException
{
if (value == null)
st.setNull (index, Hibernate.STRING.sqlType ());
else
{
DBEnum dbEnum = (DBEnum)value;
value = dbEnum.getDBCode();
st.setString (index, dbEnum.getDBCode());
}
if (IS_VALUE_TRACING_ENABLED)
{
log.trace (getClass().getName()+" "+value);
}
}
}
界面:
public interface DBEnum
{
public String getDBCode ();
}
最后,您必须DBEnumType
为要映射的每个枚举类型进行扩展:
public class DBEnumCardType extends DBEnumType
{
public Class returnedClass ()
{
return Status.class;
}
public Object toEnum (String value)
{
return Status.fromDBCode (value);
}
}
在Status
中,您必须实现将 DB 代码映射到枚举的静态方法:
private final static Map<String, Status> dbCode2Enum = new HashMap<String, Status> ();
static {
for (Status enm: Status.values ())
{
String key = enm.getDBCode ();
if (dbCode2Enum.containsKey (key))
throw new ShouldNotHappenException ("Duplicate key "+key+" in "+enm.getClass ());
dbCode2Enum.put (key, enm);
}
}
private String dbCode;
private Status (String dbCode)
{
this.dbCode = dbCode;
}
public String getDBCode ()
{
return dbCode;
}
public static Status fromDBCode (String dbCode)
{
if (dbCode == null)
return null;
Status result = dbCode2Enum.get (dbCode);
if (result == null)
throw new ShouldNotHappenException ("Can't find key "+dbCode+" in "+Status.class);
return result;
}
最后,您必须使用注解@org.hibernate.annotations.Type()
告诉 Hibernate 使用自定义映射。
结论:不要使用自定义代码。他们只会生成很多愚蠢的样板代码,您无法排除这些代码。