在绝大数的情况下,typeHandler因为枚举类而使用,MyBatis已经定义了两个类作为枚举类的支持,这两个类是
- EnumOrdinalTypeHandler
- EnumTypeHandler
前者是按mybatis根据枚举数组下标索引的方式进行匹配的,它要求数据库返回一个整数作为其下标,它会根据下标找到对应的枚举类型,后者是EnumTypeHandler会把使用的名称转化为对应的枚举,具体的在实例在进行解释
首先先来建立一个性别的枚举类-SexEnum
package com.learn.ssm.chapter4.enumeration;
public enum SexEnum {
MALE(1,"男"),
FEMALE(0,"女");
private int id;
private String name;
public int getId() {
return id;
}
public void setId(int id) {
this.id = id;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
//构造方法
SexEnum(int id,String name){
this.id=id;
this.name=name;
}
public static SexEnum getSexById(int id){
for(SexEnum sex:SexEnum.values()){
if(sex.getId()==id){
return sex;
// 返回male或者fmale,是为了后面的自定义的typehandler
}
}
return null;
}
// public static void main(String[] args) {
// SexEnum[] season1 = SexEnum.values();
// System.out.println();
// System.out.println(season1[0].getSexById(season1[0].getId()).getName());
// // 枚举类的使用方法,values是枚举型数据的声明值,比如MALE,返回的是一个数组、
// }
}
为了使用这个关于性别的枚举类,先创建一个pojo类
package com.learn.ssm.chapter3.pojo;
import com.learn.ssm.chapter4.enumeration.SexEnum;
public class User {
private Long id;
private String userName;
private String password;
private SexEnum sex;
// 枚举类的sex
private String mobile;
private String tel;
private String email;
private String note;
/** setter and getter **/
public Long getId() {
return id;
}
public void setId(Long id) {
this.id = id;
}
public String getUserName() {
return userName;
}
public void setUserName(String userName) {
this.userName = userName;
}
public String getPassword() {
return password;
}
public void setPassword(String password) {
this.password = password;
}
public SexEnum getSex() {
return sex;
}
public void setSex(SexEnum sex) {
this.sex = sex;
}
public String getMobile() {
return mobile;
}
public void setMobile(String mobile) {
this.mobile = mobile;
}
public String getTel() {
return tel;
}
public void setTel(String tel) {
this.tel = tel;
}
public String getEmail() {
return email;
}
public void setEmail(String email) {
this.email = email;
}
public String getNote() {
return note;
}
public void setNote(String note) {
this.note = note;
}
}
数据库设计如下:
EnumOrdinalTypeHandler
为了测试,可以创建一个UserMapper.xml
<?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.learn.ssm.chapter3.mapper.UserMapper">
<resultMap id="userMapper" type="user">
<result property="id" column="id" />
<result property="userName" column="user_name" />
<result property="password" column="password" />
<result property="sex" column="sex"
typeHandler="org.apache.ibatis.type.EnumOrdinalTypeHandler"/>
<!-- typeHandler="com.learn.ssm.chapter4.typehandler.SexEnumTypeHandler"/> -->
<!--
<result property="sex" column="sex"
typeHandler="org.apache.ibatis.type.EnumTypeHandler"/>
-->
<!--
<result property="sex" column="sex"
typeHandler="com.learn.ssm.chapter4.typehandler.SexEnumTypeHandler"/>
-->
<result property="mobile" column="mobile" />
<result property="tel" column="tel" />
<result property="email" column="email" />
<result property="note" column="note" />
</resultMap>
<select id="getUser" resultMap="userMapper" parameterType="long">
select id, user_name, password, sex, mobile, tel, email, note from t_user
where id = #{id}
</select>
</mapper>
因为枚举类声明的顺序是:MALE(1,"男"),FEMALE(0,"女");
所以sex字段在数据库设计为1的时候,返回的结果是女性。mybatis自动把sex字段的值转为int类型,因为在执行EnumOrdinalTypeHandler是根据mybatis返回的数组索引进行匹配的,所以要求数据库返回的是一个整数,如果不是整数,会报错误
测试类:
private static void testTypeHandler() {
Logger log = Logger.getLogger(chapter4Main.class);
SqlSession sqlSession = null;
try {
sqlSession = SqlSessionFactoryUtils.openSqlSession();
UserMapper userMapper = sqlSession.getMapper(UserMapper.class);
User user = userMapper.getUser(1L);
// 自带的EnumordinalTypeHandler和EnumTypehandler前置存储的是枚举的顺序号,后者是枚举实例名,但是有时候我们想用枚举的id来确定。这需要自定义枚举类typeHandler
System.out.println("user的sex在这里"+user);
System.out.println("user的sex在这里"+user.getSex());
System.out.println(user.getSex().getName());
System.out.println("userName这里"+user.getUserName());
} finally {
if (sqlSession != null) {
sqlSession.close();
}
}
}
执行的日志
EnumTypeHandler
EnumTypeHandler是根据数据库返回的字符串如“MALE”或者"FEMALE",进行Enum.valueOf(SexEnum.class,"MALE")转换,多以为了测试EnumTypeHandler的转换,我们把数据库的字段的sex字段修改为字符型(varchar(10))并把数据修改为FEMALE
注意修改UserMapper.xml中的tyopehandler为EnumTypeHandler
<?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.learn.ssm.chapter3.mapper.UserMapper">
<resultMap id="userMapper" type="user">
<result property="id" column="id" />
<result property="userName" column="user_name" />
<result property="password" column="password" />
<result property="sex" column="sex"
typeHandler="org.apache.ibatis.type.EnumTypeHandler"/>
<!-- typeHandler="com.learn.ssm.chapter4.typehandler.SexEnumTypeHandler"/> -->
<!--
<result property="sex" column="sex"
typeHandler="org.apache.ibatis.type.EnumTypeHandler"/>
-->
<!--
<result property="sex" column="sex"
typeHandler="com.learn.ssm.chapter4.typehandler.SexEnumTypeHandler"/>
-->
<result property="mobile" column="mobile" />
<result property="tel" column="tel" />
<result property="email" column="email" />
<result property="note" column="note" />
</resultMap>
<select id="getUser" resultMap="userMapper" parameterType="long">
select id, user_name, password, sex, mobile, tel, email, note from t_user
where id = #{id}
</select>
</mapper>
自定义枚举typeHandler
我们已经讨论了Mybatis内部提供的两种转换的typeHandler,但是他们有很大的局限性,更多的时候我们希望使用自定义的typeHandler,修改数据库为以下:
其中sex的数据类型改为int(10)
此时,按SexEnum的定义,sex=1为男性,sex=0为女性。为了满足这个规则,让我们自定义一个SexEnumTypeHandler
package com.learn.ssm.chapter4.typehandler;
import java.sql.CallableStatement;
import java.sql.JDBCType;
import java.sql.PreparedStatement;
import java.sql.ResultSet;
import java.sql.SQLException;
import org.apache.ibatis.type.JdbcType;
import org.apache.ibatis.type.TypeHandler;
import com.learn.ssm.chapter4.enumeration.SexEnum;
public class SexEnumTypeHandler implements TypeHandler<SexEnum> {
@Override
public void setParameter(PreparedStatement ps, int i, SexEnum parameter,
JdbcType jdbcType) throws SQLException {
ps.setInt(i, parameter.getId());
// 是使用typeHandler通过preparedStatment对象进行设置SQL参数的时候使用的具体方法,i是SQL的下标,parameter是参数,jdbcType是数据库类型
// 执行预编译sql
}
@Override
public SexEnum getResult(ResultSet rs, String columnName)
throws SQLException {
int id = rs.getInt(columnName);
return SexEnum.getSexById(id);
}
@Override
public SexEnum getResult(ResultSet rs, int columnIndex) throws SQLException {
int id = rs.getInt(columnIndex);
return SexEnum.getSexById(id);
}
@Override
public SexEnum getResult(CallableStatement cs, int columnIndex)
throws SQLException {
int id = cs.getInt(columnIndex);
return SexEnum.getSexById(id);
}
}
然后修改UserMapper.xml中的
<result property="sex" column="sex"
typeHandler="com.learn.ssm.chapter4.typehandler.SexEnumTypeHandler"/>```