Mybatis下基于注解的Enum类型直接存储与读写
背景知识
做业务时,有些常见属性会存成Enum类型,便于代码复用,比如性别male,female,other,nolimit。当这些属性需要存储到DB中时,我们可能会为Enum指定code,name这样的属性,再将code按照int,name按照varchar存储。读写的时候再进行转换。
实际上,mybatis默认的handler中已经提供了不同的解决方案,便于我们直接读写。
mybatis默认提供了两种Enum类型的handler,EnumTypeHandler
和EnumOrdinalTypeHandler
。
- EnumTypeHandler是将Enum按照String处理,存储为varchar
- EnumOrdinalTypeHandler是将Enum按照int处理,存储为int(smallint,tinyint也可)
示例代码
Enum类
public enum Gender{
male,
female,
other,
umlimit
}
Entity类
Entity中应该将对应的Filed直接设成Enum。
@Table(name = "t_people_info")
public class PeopleInfo{
...
@Id
@GeneratedValue(strategy = GenerationType.IDENTITY)
private Long id;
@Column(name = "gender")
private Gender gender;
public Gender getGender(){return gender;}
public void setGender(Gender gender){this.gender = gender;}
...
}
Mapper类
public interface PeopleInfoMapper{
@Insert("INSERT INTO people_info (gender,,...) VALUES (#{gender,javaType=com.aerexu.test.Gender,jdbcType=VARCHAR},....) ")
int insertPeopleInfo(@Param("gender") Gender gender,...);
@Select("SELECT (id,gender,...) WHERE id=#{id}")
@Results(value = {
@Result(column = "id", property = "id", jdbcType = JdbcType.BIGINT, javaType = Long.class),
@Result(column = "gender", property = "gender",jdbcType = JdbcType.VARCHAR, javaType = Gender.class)
})
PeopleInfo selectPeopleInfo(@Param("id") long id);
}
Handler注册
声明和定义好相关的类和接口之后,需要将Handler和定义的Enum对应起来,需要在SqlSessionFactory
中进行注册。
@PostConstruct
@Autowired
private void specialTypeHandlerRegistry(SqlSessionFactory sqlSessionFactory) {
TypeHandlerRegistry typeHandlerRegistry = sqlSessionFactory.getConfiguration().getTypeHandlerRegistry();
typeHandlerRegistry.register(Gender.class, JdbcType.VARCHAR, EnumTypeHandler.class);
}
替换为EnumOrdinalTypeHandler
如果想让Enum在数据库中存储的是数字而不是字符串,仅需将上述的JdbcType.VARCHAR
替换为JdbcType.TINYINT
,并将EnumTypeHandler.class
替换为EnumOrdinalTypeHandler.class
Extra
Java中Enum类
Enum是默认提供了name()
和ordinal()
两个方法的,分别对应了Enum示例的名字(声明的全小写)和顺序(从0开始计数)。Mybatis的Enum默认的handler分别对应这两种情形。
Mybatis的handler注册
Mybatis在读取数据进行javaType和jdbcType的转换时,是各个预先映射好的handler处理的。映射信息存储在TypeHandlerRegistry
类的TYPE_HANDLER_MAP中,其定义为Map<Type, Map<JdbcType, TypeHandler<?>>>
。可见,Typehandler是javaType和jdbcType唯一映射的。当有一些自己定义的javaType或者Typehandler时,mybatis并不会初始化映射关系,必须由代码主动注册。