0
点赞
收藏
分享

微信扫一扫

mybatis 中使用枚举

后来的六六 2022-12-03 阅读 135


文章目录

  • ​​mybatis 中使用枚举​​
  • ​​1. 内置枚举转换器​​
  • ​​1.1 内置枚举转换器介绍​​
  • ​​1.1.1 EnumTypeHandler​​
  • ​​1.1.2 EnumOrdinalTypeHandler​​
  • ​​1.2 内置枚举转换器使用​​
  • ​​2. 自定义类型转换器​​
  • ​​2.1 BaseTypeHandler 抽象类​​
  • ​​2.2 自定义枚举转换器实现​​
  • ​​2.2.1 枚举接口​​
  • ​​2.2.2 自定义类型转换器​​
  • ​​2.3 自定义枚举转换器测试​​
  • ​​2.3.1 用户实体对象​​
  • ​​2.3.2 控制层​​
  • ​​2.3.3 接口层​​
  • ​​2.3.4 接口实现层​​
  • ​​2.3.5 持久层​​
  • ​​2.3.6 mybatis 配置文件​​
  • ​​2.3.7 mybatis 映射文件​​
  • ​​2.4 数据库脚本​​
  • ​​2.5 接口测试​​
  • ​​2.6 Reference​​


 

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 接口测试

mybatis 中使用枚举_bc


 

2.6 Reference

  • ​​github 源码地址​​
  • ​​如何在MyBatis中优雅的使用枚举​​
  • ​​学习Spring Boot:(十二)Mybatis 中自定义枚举转换器​​


举报

相关推荐

0 条评论