#概述
在项目开发过程中经常会遇到数据库存储的是数值,在Java代码枚举表示的字段。这些字段在存储和查询时需要做一个转换:写数据库的时候将枚举转换为数字,读数据库时将数字转换为枚举。
下面介绍一种通过mybatis注解实现数据类型自动转换的方式。该方式能处理所有存储模型和内存模型的数据类型不一致的场景,不局限于枚举和int值。
#一、在tbl_user表中增加一个字段sex用于表示性别
性别定义为数值类型,用不同数字代表不同的性别。
CREATE TABLE `tbl_user` (
`id` int(11) NOT NULL AUTO_INCREMENT,
`name` varchar(255) NOT NULL DEFAULT '',
`age` int(4) NOT NULL DEFAULT '0',
`sex` int(2) NOT NULL DEFAULT '-1' COMMENT ' 性别。 1-男; 2-女',
PRIMARY KEY (`id`)
) ENGINE=InnoDB AUTO_INCREMENT=14 DEFAULT CHARSET=utf8;
#二、定义Java bean使用枚举类型
在Java 中使用枚举,保证数据的合法性。
package com.elon.springbootdemo.model;
import com.elon.springbootdemo.constant.EnumSexType;
public class User
{
private int userId = -1;
private String name = "";
private int age = -1;
private EnumSexType sexType = EnumSexType.NA;
@Override
public String toString()
{
return "name:" + name + "|age:" + age;
}
public int getUserId()
{
return userId;
}
public void setUserId(int userId)
{
this.userId = userId;
}
public String getName()
{
return name;
}
public void setName(String name)
{
this.name = name;
}
public int getAge()
{
return age;
}
public void setAge(int age)
{
this.age = age;
}
public EnumSexType getSexType() {
return sexType;
}
public void setSexType(EnumSexType sexType) {
this.sexType = sexType;
}
}
#三、EnumSexType枚举类型定义
package com.elon.springbootdemo.constant;
/**
* 性别类型定义。
*
* @author elon
* @version 2018年4月2日
*/
public enum EnumSexType {
NA(-1), //无效值
MAN(1), //男
WOMAN(2); //女
private int type;
private EnumSexType(int type) {
this.type = type;
}
public int getType() {
return type;
}
public static EnumSexType int2Enum(int sexType) {
EnumSexType[] types = EnumSexType.values();
for (EnumSexType type : types) {
if (type.getType() == sexType) {
return type;
}
}
return EnumSexType.NA;
}
}
#四、定义枚举类型转换处理类
定义了如下处理类后,mybatis在查询数据和写数据时会拦截相应类型的字段,调用重载的方法做类型转换:
package com.elon.springbootdemo.constant;
import java.sql.CallableStatement;
import java.sql.PreparedStatement;
import java.sql.ResultSet;
import java.sql.SQLException;
import org.apache.ibatis.type.JdbcType;
import org.apache.ibatis.type.TypeHandler;
/**
* 性别枚举转换处理类。
*
* @author elon
* @version 2018年4月2日
*/
public class EnumSexTypeHandler implements TypeHandler {
@Override
public EnumSexType getResult(ResultSet arg0, String arg1) throws SQLException {
return EnumSexType.int2Enum(arg0.getInt(arg1));
}
@Override
public EnumSexType getResult(ResultSet arg0, int arg1) throws SQLException {
return EnumSexType.int2Enum(arg0.getInt(arg1));
}
@Override
public EnumSexType getResult(CallableStatement arg0, int arg1) throws SQLException {
return EnumSexType.int2Enum(arg0.getInt(arg1));
}
@Override
public void setParameter(PreparedStatement arg0, int arg1, EnumSexType arg2, JdbcType arg3) throws SQLException {
arg0.setInt(arg1, arg2.getType());
}
}
#五、在插入数据和查询数据时使用typeHandler
package com.elon.springbootdemo.mapper;
import java.util.List;
import org.apache.ibatis.annotations.Insert;
import org.apache.ibatis.annotations.Options;
import org.apache.ibatis.annotations.Result;
import org.apache.ibatis.annotations.Results;
import org.apache.ibatis.annotations.Select;
import com.elon.springbootdemo.constant.EnumSexTypeHandler;
import com.elon.springbootdemo.model.User;
/**
* 用户数据管理Mapper。
*
* @author elon
* @version 2018年4月2日
*/
public interface UserMapperV2 {
/**
* 插入用户数据。
*
* @param user
*/
@Insert("insert into tbl_user ("
+ "name,"
+ "age,"
+ "sex"
+ ") values ("
+ "#{name}, "
+ "#{age},"
+ "#{sexType, typeHandler=com.elon.springbootdemo.constant.EnumSexTypeHandler})")
@Options(useGeneratedKeys=true, keyProperty="userId", keyColumn="id")
void insertUser(User user);
/**
* 获取所有的用户数据。
*
* @return
*/
@Select("select id, name, age, sex from tbl_user")
@Results({
@Result(property="userId", column="id"),
@Result(property="name", column="name"),
@Result(property="age", column="age"),
@Result(property="sexType", column="sex", typeHandler=EnumSexTypeHandler.class)
})
List getAllUsers();
}
通过上面定义的typeHandler, 开发者可以在java代码中使用枚举定义,数据库使用int(其它也可)类型。既拥有了枚举类型的合法性保证,也保证了数据库查询效率。