在设计数据库的时候,我们有时候会把表里的某个字段的值设置为数字或者为英文来表示他的一些特殊含义。就拿设置成数字来说,假如1对应是学生,2对应是教师,在java里面定义成这样的枚举,但是一般使用mybatis查出来的话,我们想要让它自动装换成我们想要的枚举,不需要再手动根据数值去判断设置成我们想要的枚举。要是实现这样的效果,那么我们就要用到mybatis的BaseTypeHandler了。
让我们来看看要继承BaseTypeHandler这个抽象类,需要覆写哪些方法:
public abstract void setNonNullParameter(PreparedStatement ps, int i, T parameter, JdbcType jdbcType) throws SQLException;
public abstract T getNullableResult(ResultSet rs, String columnName) throws SQLException;
public abstract T getNullableResult(ResultSet rs, int columnIndex) throws SQLException;
public abstract T getNullableResult(CallableStatement cs, int columnIndex) throws SQLException;
实现了这些抽象类,当得到结果集的时候,程序就会回调这些方法,例如根据名称获取当前行的某一列的值,那么就会直接回调getNullableResult(ResultSet rs, String columnName)这个方法,根据名称得到当行的当前列的值,然后我们在这里去调用枚举,匹配枚举中的每一个值,相等的话直接返回该枚举,达到自动转换成我们想要的枚举的效果。其他的重载方法类似,只不过是有些根据列索引,有些根据列名称做枚举自动转换而已。
好了,介绍就到这里,让我们来看看具体实现。。
package net.itaem.less;
import java.util.HashMap;
import java.util.Map;
/**
* @author: Fighter168
*/
public enum PersonType{
STUDENT("1","学生"),
TEACHER("2","教师");
private String value;
private String displayName;
static Map enumMap=new HashMap();
static{
for(PersonType type:PersonType.values()){
enumMap.put(type.getValue(), type);
}
}
private PersonType(String value,String displayName) {
this.value=value;
this.displayName=displayName;
}
public String getValue() {
return value;
}
public void setValue(String value) {
this.value = value;
}
public String getDisplayName() {
return displayName;
}
public void setDisplayName(String displayName) {
this.displayName = displayName;
}
public static PersonType getEnum(String value) {
return enumMap.get(value);
}
}
/**
* @author: Fighter168
*/
public class Person {
private String id;
private String name;
//枚举
private PersonType personType;
//set get 方法。。
}
/**
* @author: Fighter168
*/
public interface PersonDao {
public List query();
}
package net.itaem.handler;
import java.sql.CallableStatement;
import java.sql.PreparedStatement;
import java.sql.ResultSet;
import java.sql.SQLException;
import net.itaem.less.PersonType;
import org.apache.ibatis.type.BaseTypeHandler;
import org.apache.ibatis.type.JdbcType;
/**
* @author: Fighter168
*/
public class PersonTypeHandler extends BaseTypeHandler{
private Class type;
private PersonType[] enums;
/**
* 设置配置文件设置的转换类以及枚举类内容,供其他方法更便捷高效的实现
* @param type 配置文件中设置的转换类
*/
public PersonTypeHandler(Class 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.");
}
@Override
public PersonType getNullableResult(ResultSet rs, String columnName) throws SQLException {
// 根据数据库存储类型决定获取类型,本例子中数据库中存放String类型
String i = rs.getString(columnName);
if (rs.wasNull()) {
return null;
} else {
// 根据数据库中的value值,定位PersonType子类
return PersonType.getEnum(i);
}
}
@Override
public PersonType getNullableResult(ResultSet rs, int columnIndex) throws SQLException {
// 根据数据库存储类型决定获取类型,本例子中数据库中存放String类型
String i = rs.getString(columnIndex);
if (rs.wasNull()) {
return null;
} else {
// 根据数据库中的value值,定位PersonType子类
return PersonType.getEnum(i);
}
}
@Override
public PersonType getNullableResult(CallableStatement cs, int columnIndex) throws SQLException {
// 根据数据库存储类型决定获取类型,本例子中数据库中存放String类型
String i = cs.getString(columnIndex);
if (cs.wasNull()) {
return null;
} else {
// 根据数据库中的value值,定位PersonType子类
return PersonType.getEnum(i);
}
}
@Override
public void setNonNullParameter(PreparedStatement ps, int i, PersonType parameter, JdbcType jdbcType)
throws SQLException {
// baseTypeHandler已经帮我们做了parameter的null判断
ps.setString(i, parameter.getValue());
}
}
其实handler还可以写在PersonMapper.xml这里,写成下面这样:
下面是为mybatis创建配置文件cfg.xml
/**
* @author: Fighter168
*/
public class SpringTest {
public static void main(String[] args) {
ApplicationContext context=new ClassPathXmlApplicationContext("resource/ApplicationContext.xml");
PersonDao personDao=(PersonDao) context.getBean("personDao");
List list=personDao.query();
for(Person p:list){
System.out.println(p.toString());
}
}
}
也许我们还在想,如果我们有几十个枚举,这样转换的话,那我们岂不是要分别为每一个枚举定义一个Handler,然后为每一个Handler注册。其实不必这样,我们可以定义成一个通用的枚举转换处理器,具体怎么实现呢,下一篇博客我会告诉大家 mybatis枚举自动转换(通用转换处理器实现)