#1. Java默认枚举类存在的问题 Java的枚举类的设计不能很好的满足中文应用的需求,因为它只提供了2个属性:name(String)和ordinal(Integer)。 而我们在应用枚举时通常需要3个属性:
- name(String):英文名称,编码时用,可以沿用Java枚举的name。
- text(String):枚举文本,用于在页面显示。
- value(String):枚举值,用于数据库存储。
以最常见的 Sex(性别) 枚举类来举例:
- name:MALE/FEMALE
- text:男/女
- value:1/2
这是一个在应用中经常遇见的需求,从上面的例子可以看到,text在Java枚举类中没有对应属性,而value用ordinal又不合适。这样我们需要在枚举类中定义text和value两个属性,以满足应用的需求。为了能够统一的处理这样的枚举类型,首先得定义一个枚举类的接口,因为枚举类是内置的不支持继承。
#2. 创建一个枚举类型接口 从上面的需求看到,应用真正需要使用的是text和value两个属性,定义一个枚举类型接口 ,如下:
public interface IEnum { String getText(); String getValue();}
创建 (性别)的枚举类,实现IEnum接口,如下:
public enum Sex implements IEnum { MALE("男", "1"), FEMALE("女", "2"); private String text; private String value; private Sex(String text, String value) { this.text = text; this.value = value; } @Override public String getText() { return text; } @Override public String getValue() { return value; }}
#3. 创建对应的转换器 如果使用Hibernate,为了在数据层透明的存取自定义枚举类型,需要创建针对该枚举类型的UserType,可以参考这里 。
如果使用Spring MVC,为了在表现层透明的传递自定义枚举类型,需要创建针对该枚举类型的Converter,可以参考这里 和 。
有了转换器,我们就不需要另外编写代码来处理枚举类了,就像在使用一个基本类型变量一样。它可以用来当作Entity属性类型,也可以在页面的下拉列表或单选、多选框组件中方便的使用。
#4. 使用自定义枚举类 在Entity类User中使用Sex枚举类型作为属性,如下:
@Entity@Table(name = "Tmp_User")public class User extends UuidEntity { ... @Type(type = "IEnum") private Sex sex = Sex.MALE; ...}
在数据库中存入value值,在页面上展示text值,freemarker中可以这样写:${user.sex.text}
。如果需要在页面上显示一个下拉列表让用户选择性别,也很简单:通过Sex.values()
方法可以拿到枚举列表,循环枚举列表用value
和text
值填充options即可。