在开发中经常遇到一些枚举类型的字段;例如:
@Entity
@Data
@Table(name = "sys_user")
@NoArgsConstructor
@AllArgsConstructor
@Builder
@EqualsAndHashCode(callSuper = true)
public class User extends AbstractBean {
private static final long serialVersionUID = 7814370326796291722L;
@Id
@GeneratedValue(strategy = GenerationType.IDENTITY)
private Long id;
@Column(name = "create_time")
@CreationTimestamp
private Date createTime;
@Column(name = "modify_time")
@UpdateTimestamp
private Date modifyTime;
@Column(name = "phone")
private String phone;
@Column(name = "email")
private String email;
@Column(name = "password")
private String password;
@Column(name = "status")
private UserStatus status;
@Column(name = "name")
private String name;
}
UserStatus status; 用户状态
public class UserStatus extends StringEnum {
private static final long serialVersionUID = 1220048355057672045L;
public static final UserStatus CREATED = newInstance(UserStatus.class,"created", "创建");
public static final UserStatus USE = newInstance(UserStatus.class, "use", "使用");
}
数据库存储编码 “created”,Java 映射对象 CREATED;
这种场景是非常常见的,类型,状态,,,,等字段都可以这样搞。
实现方案: 实现UserType接口
@Data
public class StringEnum extends AbstractSimpleField implements UserType {
private static final long serialVersionUID = 1732002864737498898L;
private static final Logger LOGGER = LoggerFactory.getLogger(StringEnum.class);
String code;
String value;
/**
* 因为我只存入code 所以这里只要一个值就行。 不同的类型可以查看Types对应的类型
*/
private static final int[] SQL_TYPES = { Types.VARCHAR };
@Override
public int[] sqlTypes() {
return SQL_TYPES;
}
/**
* 返回的类型
* @return class
*/
@Override
public Class returnedClass() {
return StringEnum.class;
}
/**
* 重写 equals
* @param x 对象x
* @param y 对象y
* @return boolean
* @throws HibernateException 异常
*/
@Override
public boolean equals(Object x, Object y) throws HibernateException {
boolean result = false;
if (x == y) result = true;
if (x == null || y == null) result = false;
if (x instanceof StringEnum && y instanceof StringEnum) {
result = ((StringEnum) x).getCode().equals(((StringEnum) y).getCode());
}
return result;
}
/**
* 重写 hashCode
* @param o 对象o
* @return int
* @throws HibernateException 异常
*/
@Override
public int hashCode(Object o) throws HibernateException {
StringEnum stringEnum = (StringEnum) o;
return stringEnum.hashCode();
}
/**
* 查询出来的code 生成对应的 StringEnum
* @param resultSet 结果集
* @param strings 字段集合--只有code
* @param sharedSessionContractImplementor session
* @param o 查询的对象
* @return StringEnum
* @throws HibernateException 异常
* @throws SQLException 异常
*/
@Override
public Object nullSafeGet(ResultSet resultSet, String[] strings, SharedSessionContractImplementor sharedSessionContractImplementor, Object o) throws HibernateException, SQLException {
// 结果集为 null 直接返回
if (resultSet == null || resultSet.wasNull()) return null;
// 获取code编码
String code = resultSet.getString(strings[0]);
// 获取 枚举属性类型
Class clazz = this.getClass();
// 返回对应的枚举
return allSimpleFields.get(getKey(clazz, code));
}
/**
* 新增和修改时,设置保存的code
* @param preparedStatement 预编译SQL语句的对象
* @param o 插入的数据
* @param i 占位符
* @param sharedSessionContractImplementor session
* @throws HibernateException 异常
* @throws SQLException 异常
*/
@Override
public void nullSafeSet(PreparedStatement preparedStatement, Object o, int i, SharedSessionContractImplementor sharedSessionContractImplementor) throws HibernateException, SQLException {
if (o == null){
preparedStatement.setNull(i, Types.VARCHAR);
}else{
StringEnum stringEnum = (StringEnum) o;
preparedStatement.setString(i, stringEnum.getCode());
}
}
@Override
public Object deepCopy(Object o) throws HibernateException {
return o;
}
@Override
@Transient
public boolean isMutable() {
return false;
}
@Override
public Serializable disassemble(Object o) throws HibernateException {
return (Serializable) deepCopy(o);
}
@Override
public Object assemble(Serializable serializable, Object o) throws HibernateException {
return deepCopy(serializable);
}
@Override
public Object replace(Object o, Object o1, Object o2) throws HibernateException {
return o;
}
}
AbstractSimpleField保存所有的枚举对象
public abstract class AbstractSimpleField implements Serializable {
private static final Logger LOGGER = LoggerFactory.getLogger(AbstractSimpleField.class);
private static final long serialVersionUID = 5964652520313221077L;
/**
* 全部枚举类型
*/
static Map<String, StringEnum> allSimpleFields = new ConcurrentHashMap<>();
protected static <T extends StringEnum> T newInstance(Class<T> clazz, String code, String value){
try {
T t = clazz.newInstance();
t.setCode(code);
t.setValue(value);
allSimpleFields.put(getKey(clazz,code), t);
return t;
} catch (Exception e) {
LOGGER.error(e.getMessage());
return null;
}
}
static String getKey(Class clazz, String code){
if (clazz == null) return code;
return clazz.getName() + ":" +code;
}
}
测试
@RunWith(SpringJUnit4ClassRunner.class)
@ContextConfiguration({ "classpath:config/spring-*.xml"})
@Transactional
// 测试结束后事物是否回滚;默认true;
@Rollback(value = false)
public class UserDaoImplTest {
@Autowired
private UserDao userDao;
@Test
public void findById() {
User user = userDao.findById(1L);
if (user == null){
System.out.println("================");
}
System.out.println(user);
UserStatus userStatus = user.getStatus();
if (UserStatus.USE.equals(userStatus)){
user.setStatus(UserStatus.CREATED);
}else {
user.setStatus(UserStatus.USE);
}
userDao.save(user);
System.out.println(user);
}
}