mybatis 中使用枚举
Mybatis 中使用枚举
·
文章目录
mybatis 中使用枚举
1. 内置枚举转换器
1.1 内置枚举转换器介绍
1.1.1 EnumTypeHandler
- 默认的枚举转换器,该转换器将枚举实例转换为实例名称的字符串,即将
SexEnum.MAN
转换MAN
1.1.2 EnumOrdinalTypeHandler
- 将枚举实例的
ordinal
属性作为取值,即SexEnum.MAN
转换为0
,SexEnum.WOMAN
转换为1
MyBatis内置枚举转换器
- org.apache.ibatis.type.EnumTypeHandler
- org.apache.ibatis.type.EnumOrdinalTypeHandler
1.2 内置枚举转换器使用
mybatis-config.xml
<typeHandlers>
<typeHandler handler="org.apache.ibatis.type.EnumOrdinalTypeHandler" javaType="com.answer.aal.entity.StatusEnum" />
<typeHandler handler="org.apache.ibatis.type.EnumOrdinalTypeHandler" javaType="com.answer.aal.entity.SexEnum" />
</typeHandlers>
2. 自定义类型转换器
2.1 BaseTypeHandler 抽象类
public abstract class BaseTypeHandler<T> extends TypeReference<T> implements TypeHandler<T> {
// ...
/**
* 用于定义设置参数时,该如何把Java类型的参数转换为对应的数据库类型
* */
public abstract void setNonNullParameter(PreparedStatement ps, int i, T parameter, JdbcType jdbcType)
throws SQLException;
/**
* 用于定义通过字段名称获取字段数据时,如何把数据库类型转换为对应的Java类型
* */
public abstract T getNullableResult(ResultSet rs, String columnName) throws SQLException;
/**
* 用于定义通过字段索引获取字段数据时,如何把数据库类型转换为对应的Java类型
* */
public abstract T getNullableResult(ResultSet rs, int columnIndex) throws SQLException;
/**
* 用定义调用存储过程后,如何把数据库类型转换为对应的Java类型
* */
public abstract T getNullableResult(CallableStatement cs, int columnIndex) throws SQLException;
}
2.2 自定义枚举转换器实现
2.2.1 枚举接口
枚举通用行为接口: IEnum
public interface IEnum<E extends Enum<?>, T> {
T getValue();
}
性别枚举: SexEnum
public enum SexEnum implements IEnum<EducationEnum, Integer> {
/** 男 */
MAN(0),
/** 女 */
WOMAN(1);
private int value;
SexEnum(int value) {
this.value = value;
}
@Override
public Integer getValue() {
return value;
}
}
学历枚举: EducationEnum
public enum EducationEnum implements IEnum<EducationEnum, String> {
/** 小学 */
PRIMARY_SCHOOL("PRIMARY"),
/**
* 初中
* */
JUNIOR_SCHOOL("JUNIOR"),
/**
* 高中
* */
HIGH_SCHOOL("HIGH"),
/**
* 大学
* */
UNIVERSITY_SCHOOL("UNIVERSITY")
;
private String value;
EducationEnum(String value) {
this.value = value;
}
@Override
public String getValue() {
return value;
}
}
2.2.2 自定义类型转换器
import org.apache.ibatis.type.BaseTypeHandler;
import org.apache.ibatis.type.JdbcType;
import org.apache.ibatis.type.MappedTypes;
import java.sql.CallableStatement;
import java.sql.PreparedStatement;
import java.sql.ResultSet;
import java.sql.SQLException;
import java.util.Objects;
@MappedTypes(value = {SexEnum.class, EducationEnum.class})
public class BaseEnumTypeHandler<E extends Enum<E> & IEnum> extends BaseTypeHandler<E> {
/**
* 枚举的class
*/
private Class<E> type;
/**
* 枚举的每个子类枚
*/
private E[] enums;
/**
* 一定要有默认的构造函数, 不然抛出 not found method 异常
*/
public BaseEnumTypeHandler() {
}
/**
* 设置配置文件设置的转换类以及枚举类内容, 供其他方法更便捷高效的实现
*
* @param type 配置文件中设置的转换类
*/
public BaseEnumTypeHandler(Class<E> type) {
if (type == null) {
throw new IllegalArgumentException("Type argument cannot be null");
}
this.type = type;
this.enums = type.getEnumConstants();
if (this.enums == null) {
throw new IllegalArgumentException(type.getSimpleName()
+ " does not represent an enum type.");
}
}
/**
* 用于定义设置参数时,该如何把Java类型的参数转换为对应的数据库类型
* */
@Override
public void setNonNullParameter(PreparedStatement ps, int i, E parameter,
JdbcType jdbcType) throws SQLException {
/*
* BaseTypeHandler已经帮我们做了parameter的null判断
* 数据库存储的是枚举的值, 所以我们这里使用 value , 如果需要存储 name, 可以自定义修改
*/
if (jdbcType == null) {
ps.setString(i, Objects.toString(parameter.getValue()));
} else {
ps.setObject(i, parameter.getValue(), jdbcType.TYPE_CODE);
}
}
/**
* 用于定义通过字段名称获取字段数据时,如何把数据库类型转换为对应的Java类型
* */
@Override
public E getNullableResult(ResultSet rs, String columnName)
throws SQLException {
String i = rs.getString(columnName);
if (rs.wasNull()) {
return null;
} else {
return locateEnumStatus(i);
}
}
/**
* 用于定义通过字段索引获取字段数据时,如何把数据库类型转换为对应的Java类型
* */
@Override
public E getNullableResult(ResultSet rs, int columnIndex)
throws SQLException {
String i = rs.getString(columnIndex);
if (rs.wasNull()) {
return null;
} else {
return locateEnumStatus(i);
}
}
/**
* 用定义调用存储过程后,如何把数据库类型转换为对应的Java类型
* */
@Override
public E getNullableResult(CallableStatement cs, int columnIndex)
throws SQLException {
String i = cs.getString(columnIndex);
if (cs.wasNull()) {
return null;
} else {
return locateEnumStatus(i);
}
}
/**
* 枚举类型转换
*
* @param value 数据库中存储的自定义value属性
* @return value 对应的枚举类
*/
private E locateEnumStatus(String value) {
for (E e : enums) {
if (Objects.toString(e.getValue()).equals(value)) {
return e;
}
}
throw new IllegalArgumentException("未知的枚举类型:" + value + ",请核对"
+ type.getSimpleName());
}
}
注意: 如果使用了
@MappedTypes
注解, 需要在application.properties
中添加如下配置
# 类型处理器类所在的包路径. eg: BaseEnumTypeHandler
mybatis.type-handlers-package=com.answer.aal.entity
否则, 直接在 mybatis 配置文件
mybatis-config.xml
添加如下配置
<typeHandlers>
<typeHandler handler="com.answer.aal.entity.BaseEnumTypeHandler" javaType="com.answer.aal.entity.EducationEnum" />
<typeHandler handler="com.answer.aal.entity.BaseEnumTypeHandler" javaType="com.answer.aal.entity.SexEnum" />
</typeHandlers>
2.3 自定义枚举转换器测试
2.3.1 用户实体对象
import com.fasterxml.jackson.annotation.JsonFormat;
import lombok.Data;
import lombok.NoArgsConstructor;
import java.util.Date;
@Data
/**
* MyBatis 映射的实体对象必须提供一个无参构造方法
* */
@NoArgsConstructor
public class User {
/**
* 主键ID
* */
private Long id;
private String userName;
private SexEnum sex;
@JsonFormat(pattern = "yyyy-MM-dd")
private Date birthDay;
private EducationEnum education;
@JsonFormat(pattern = "yyyy-MM-dd HH-mm-ss")
private Date createTime;
@JsonFormat(pattern = "yyyy-MM-dd HH-mm-ss")
private Date updateTime;
public User(String userName, SexEnum sex, Date birthDay, EducationEnum education, Date createTime, Date updateTime) {
this.userName = userName;
this.sex = sex;
this.birthDay = birthDay;
this.education = education;
this.createTime = createTime;
this.updateTime = updateTime;
}
}
2.3.2 控制层
import com.answer.aal.entity.SexEnum;
import com.answer.aal.entity.EducationEnum;
import com.answer.aal.entity.User;
import com.answer.aal.service.IUserService;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.PathVariable;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;
import java.util.Date;
import java.util.List;
@RestController
@RequestMapping(value = "/user")
public class UserController {
@Autowired
private IUserService userService;
@RequestMapping("findUsers")
public List<User> findUsers() {
return userService.findUsers();
}
@RequestMapping("finUserById/{id}")
public User finUserById(@PathVariable("id") Long id) {
return userService.findUserById(id);
}
@RequestMapping("insert")
public Long insert(){
User user = new User("AnsweAIL", SexEnum.MAN, new Date(), EducationEnum.HIGH_SCHOOL, new Date(), new Date());
return userService.insertUer(user);
}
}
2.3.3 接口层
import com.answer.aal.entity.User;
import java.util.List;
public interface IUserService {
List<User> findUsers();
User findUserById(Long id);
Long insertUer(User user);
}
2.3.4 接口实现层
import com.answer.aal.dao.UserDao;
import com.answer.aal.entity.User;
import com.answer.aal.service.IUserService;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import java.util.List;
@Service
public class UserServiceImpl implements IUserService {
@Autowired
private UserDao userDao;
@Override
public List<User> findUsers() {
return userDao.findUsers();
}
@Override
public User findUserById(Long id) {
return userDao.findUserById(id);
}
@Override
public Long insertUer(User user) {
return userDao.insertUer(user);
}
}
2.3.5 持久层
import com.answer.aal.entity.User;
import java.util.List;
public interface UserDao {
List<User> findUsers();
User findUserById(Long id);
Long insertUer(User user);
}
2.3.6 mybatis 配置文件
<?xml version="1.0" encoding="UTF-8" ?>
<!DOCTYPE configuration PUBLIC "-//mybatis.org//DTD Config 3.0//EN" "http://mybatis.org/dtd/mybatis-3-config.dtd">
<configuration>
<settings>
<setting name="mapUnderscoreToCamelCase" value="true"/>
</settings>
<typeAliases>
<typeAlias alias="User" type="com.answer.aal.entity.User"/>
</typeAliases>
<typeHandlers>
<!-- 如果此处配置了映射, 则 BaseEnumTypeHandler 中就不需要 @MappedTypes 注解和 application.xml 中不需要设置属性 mybatis.type-handlers-package 值 -->
<typeHandler handler="com.answer.aal.entity.BaseEnumTypeHandler" javaType="com.answer.xsf.entity.EducationEnum" />
<typeHandler handler="com.answer.xsf.entity.BaseEnumTypeHandler" javaType="com.answer.aal.entity.SexEnum" />
</typeHandlers>
</configuration>
注意: 如果 BaseEnumTypeHandler 中设置了 @MappedTypes 注解, 此步骤 mybatis 配置文件 可省去
2.3.7 mybatis 映射文件
<?xml version="1.0" encoding="UTF-8" ?>
<!DOCTYPE mapper PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN" "http://mybatis.org/dtd/mybatis-3-mapper.dtd" >
<mapper namespace="com.answer.aal.dao.UserDao" >
<resultMap id="user_mapper" type="User">
<id column="id" property="id" jdbcType="BIGINT" />
<result column="user_name" property="userName" jdbcType="VARCHAR" />
<result column="sex" property="sex" />
<result column="birth_day" property="birthDay" jdbcType="DATE" />
<result column="education" property="education" />
<result column="create_time" property="createTime" jdbcType="TIMESTAMP" />
<result column="update_time" property="updateTime" jdbcType="TIMESTAMP" />
</resultMap>
<sql id="user_columns">
id, user_name, sex, birth_day, education, create_time, update_time
</sql>
<select id="findUsers" resultMap="user_mapper">
select <include refid="user_columns" />
from sf_user
</select>
<select id="findUserById" resultMap="user_mapper">
select <include refid="user_columns" />
from sf_user
where id = #{id}
</select>
<insert id="insertUer" useGeneratedKeys="true" keyProperty="id">
insert into sf_user
<trim prefix="(" suffix=")" suffixOverrides="," >
<if test="userName != null" >user_name,</if>
<if test="sex != null" >sex,</if>
<if test="birthDay != null" >birth_day,</if>
<if test="education != null" >education,</if>
<if test="createTime != null" >create_time,</if>
<if test="updateTime != null" >update_time,</if>
</trim>
<trim prefix="values (" suffix=")" suffixOverrides="," >
<if test="userName != null" >#{userName},</if>
<if test="sex != null" >#{sex},</if>
<if test="birthDay != null" >#{birthDay},</if>
<if test="education != null" >#{education},</if>
<if test="createTime != null" >#{createTime},</if>
<if test="updateTime != null" >#{updateTime},</if>
</trim>
</insert>
</mapper>
2.4 数据库脚本
CREATE TABLE `sf_user` (
`id` bigint(18) NOT NULL AUTO_INCREMENT,
`user_name` varchar(20) DEFAULT NULL,
`sex` enum('1','0') DEFAULT '0',
`birth_day` date DEFAULT NULL,
`education` enum('UNIVERSITY','HIGH','JUNIOR','PRIMARY') DEFAULT 'PRIMARY',
`create_time` datetime DEFAULT NULL,
`update_time` datetime DEFAULT NULL,
PRIMARY KEY (`id`)
) ENGINE=InnoDB AUTO_INCREMENT=2 DEFAULT CHARSET=utf8;
2.5 接口测试
2.6 Reference
更多推荐
已为社区贡献1条内容
所有评论(0)