如今使用Hibernater作为ORM框架时,几乎都是采用注解方式进行映射,可以映射任何类型字段。这里要说的是
映射枚举类型,在注解的方式下很容易(以后再补充),但是xml配置下就显得麻烦一点。更复杂的一种映射,就是
枚举类型存储到数据库中的类型不是字符串本身,也不是ordinal,即自定义类型数据存储。
以下以自定义类型为Integer(即存储在数据库中的是Integer类型)为例:
1. 首先创建枚举类型接口
public interface EnumsID {
String getText();
Integer getId();
}
里面定义的getId()就是我们要存储到数据库中的数据类型
2.定义枚举类型(继承上面接口)
public enum Gender implements EnumsID{
MALE(1, "男"),
FEMALE(2, "女");
private Integer id;
private String text;
private Gender(Integer id,String text){
this.id = id;
this.text = text;
}
@Override
public String getText() {
return text;
}
@Override
public Integer getId() {
return id;
}
public static Gender findById(Integer id) {
Gender[] objs = Gender.values();
for (Gender obj : objs) {
if (id.equals(obj.getId())) {
return obj;
}
}
return null;
}
}
3.编写一个转换模板,实现UserType类型接口,将枚举类型转换为Integer类型存储到数据库
import java.io.Serializable;
import java.sql.PreparedStatement;
import java.sql.ResultSet;
import java.sql.SQLException;
import java.sql.Types;
import org.hibernate.HibernateException;
import org.hibernate.engine.spi.SessionImplementor;
import org.hibernate.usertype.UserType;
public class IntegerEnumUserType<E extends Enum<E>> implements UserType {
private Class<E> clazz = null;
protected IntegerEnumUserType(Class<E> c) {
this.clazz = c;
}
private static final int[] SQL_TYPES = { Types.INTEGER };
@Override
public int[] sqlTypes() {
return SQL_TYPES;
}
@Override
public Class<E> returnedClass() {
return clazz;
}
@Override
public boolean equals(Object x, Object y) throws HibernateException {
if (x == y)
return true;
if (null == x || null == y)
return false;
return x.equals(y);
}
@Override
public int hashCode(Object x) throws HibernateException {
return x.hashCode();
}
@Override
public Object nullSafeGet(ResultSet resultSet, String[] names, SessionImplementor session, Object owner)
throws HibernateException, SQLException {
final int id = resultSet.getInt(names[0]);
if (!resultSet.wasNull()) {
try {
return clazz.getMethod("findById", new Class[] { Integer.class }).invoke(null, id);
} catch (Exception e) {
e.printStackTrace();
}
}
return null;
}
@Override
public void nullSafeSet(PreparedStatement preparedStatement, Object value, int index, SessionImplementor session)
throws HibernateException, SQLException {
if (null == value) {
preparedStatement.setNull(index, SQL_TYPES[0]);
} else {
EnumsID eID = (EnumsID) value;
preparedStatement.setInt(index, eID.getId());
}
}
@Override
public Object deepCopy(Object value) throws HibernateException {
return value;
}
@Override
public boolean isMutable() {
return false;
}
@Override
public Serializable disassemble(Object value) throws HibernateException {
return (Serializable) value;
}
@Override
public Object assemble(Serializable cached, Object owner) throws HibernateException {
return cached;
}
@Override
public Object replace(Object original, Object target, Object owner) throws HibernateException {
return original;
}
}
4.创建具体类来实现当前枚举的转换,需要继承转换模板
public class GenderEnum extends IntegerEnumUserType<Gender>{
public GenderEnum() {
super(Gender.class);
}
}
5.在XML中映射枚举类型
<property name="gender" type="com.xxx..GenderEnum">
<column name="gender">
<comment>性别 1男,2女</comment>
</column>
</property>
这样就可以在实体中使用 Gender 这个枚举类型进行操作了。
public class User{
private Integer id;
private Gender gender;
public Gender getGender() {
return this.gender;
}
public void setGender(Gender gender) {
this.gender = gender;
}
...
}