在上一篇博客里,我编写了一个UserType,实现了持久化自定义的enum类,其实那个例子中存在两个缺点。这两个缺点是关于如何正确使用enum以及generic的,她们已经和hibernate userType无关了,因此另起一个主题讨论。
在上一篇博客中,我的enum是这么写的:
public enum Status implements DescriptionID {
ACTIVATED(5, "This object is activated"),
DEACTIVATED(9, "This object is deactivated");
private Integer id;
private String description;
private static List<Status> list;
static {
list = new ArrayList<Status>(2);
list.add(ACTIVATED);
list.add(DEACTIVATED);
}
private Status(int statusNr, String description) {
this.id = statusNr;
this.description = description;
}
public String getDescription() {
return this.description;
}
public Integer getId() {
return id;
}
public static List<Status> getAll() {
return list;
}
public static Status findById(Integer id) {
for (Status status : getAll()) {
if (id == status.getId()) {
return status;
}
}
return null;
}
}
其中两个static方法是为了方便使用。
缺点一:
所有的enum实例必须手动纳入list集合中。
解决方法:
解决方法非常简单,是用Class类提供的方法getEnumConstants(), 代码如下:
public static List<Status> getAll() {
return Arrays.asList(Status.class.getEnumConstants());
}
我个人比较讨厌数组,因此这里特意将数组转换成List。如果你们不介意使用数组的话,getAll()方法完全可以省略。
缺点二:
findById(Integer id) 方法名并不贴切,叫getEnumById(Integer id)会更好些。另外一模一样的方法必须在每一个enum类中重复编写,如果某个地方需要改动,那就需要改动所有相关的enum类,这是一个很明显的bad smell。
解决方法:
编写一个util类,将逻辑转移到util类中,getEnumById(Integer id)方法调用util类中的相关方法,代码如下:
public static Status getEnumById(Integer id) {
return EnumUtils.getEnum(Status.class, id);
}
public class EnumUtils {
public static <I extends DescriptionID> I getEnum(Class<I> type, int id) {
I[] types = type.getEnumConstants();
for (I t : types) {
if (t.getId() == id)
return t;
}
return null;
}
}
这里getEnum(Class<I> type, int id)方法利用Java 5的新特性generic,利用给定的Class和enum id,返回对应的enum实例。这样处理好处很明显,获取enum实例的逻辑代码只存在与util类中,日后修改十分方便。
相关内容请参阅
我写的《Hibernate 3和Java Persistence API 程序开发从入门到精通》一书。
声明:本文版权归作者所有,如需转载请注明出处。