mybatis提供了EnumTypeHandler和EnumOrdinalTypeHandler完成枚举类型的转换,两者的功能已经基本满足了日常的使用。但是可能有这样的需求:由于某种原因,我们不想使用枚举的name和ordinal作为数据存储字段。mybatis的自定义转换类出现了。
前提知识
1. mybatis废弃了ibatis的TypeHandlerCallback接口,取而代之的接口是TypeHandler,它与原来的接口略有不同,但是方法类似。(见说明 https://code.google.com/p/mybatis/wiki/DocUpgrade3)
2. BaseTypeHandler是mybatis提供的基础转换类,该类实现了TypeHandler接口并提供很多公用方法,建议每个自定义转换类都继承它。
示例
使用一段代码,将枚举类EnumStatus中的code属性存储到数据库对应字段statusCustom。
自定义转换类
01 | package com.sg.util.typehandler; |
03 | import java.sql.CallableStatement; |
04 | import java.sql.PreparedStatement; |
05 | import java.sql.ResultSet; |
06 | import java.sql.SQLException; |
08 | import org.apache.ibatis.type.BaseTypeHandler; |
09 | import org.apache.ibatis.type.JdbcType; |
11 | import com.sg.bean.EnumStatus; |
14 | * 自定义EnumStatus转换类 <br> |
15 | * 存储属性:EnumStatus.getCode() <br> |
19 | public class EnumStatusHandler extends BaseTypeHandler<EnumStatus> { |
21 | private Class<EnumStatus> type; |
23 | private final EnumStatus[] enums; |
26 | * 设置配置文件设置的转换类以及枚举类内容,供其他方法更便捷高效的实现 |
27 | * @param type 配置文件中设置的转换类 |
29 | public EnumStatusHandler(Class<EnumStatus> type) { |
31 | throw new IllegalArgumentException( "Type argument cannot be null" ); |
33 | this .enums = type.getEnumConstants(); |
34 | if ( this .enums == null ) |
35 | throw new IllegalArgumentException(type.getSimpleName() |
36 | + " does not represent an enum type." ); |
40 | public EnumStatus getNullableResult(ResultSet rs, String columnName) throws SQLException { |
41 | // 根据数据库存储类型决定获取类型,本例子中数据库中存放INT类型 |
42 | int i = rs.getInt(columnName); |
47 | // 根据数据库中的code值,定位EnumStatus子类 |
48 | return locateEnumStatus(i); |
53 | public EnumStatus getNullableResult(ResultSet rs, int columnIndex) throws SQLException { |
54 | // 根据数据库存储类型决定获取类型,本例子中数据库中存放INT类型 |
55 | int i = rs.getInt(columnIndex); |
59 | // 根据数据库中的code值,定位EnumStatus子类 |
60 | return locateEnumStatus(i); |
65 | public EnumStatus getNullableResult(CallableStatement cs, int columnIndex) throws SQLException { |
66 | // 根据数据库存储类型决定获取类型,本例子中数据库中存放INT类型 |
67 | int i = cs.getInt(columnIndex); |
71 | // 根据数据库中的code值,定位EnumStatus子类 |
72 | return locateEnumStatus(i); |
77 | public void setNonNullParameter(PreparedStatement ps, int i, EnumStatus parameter, JdbcType jdbcType) |
79 | // baseTypeHandler已经帮我们做了parameter的null判断 |
80 | ps.setInt(i, parameter.getCode()); |
85 | * 枚举类型转换,由于构造函数获取了枚举的子类enums,让遍历更加高效快捷 |
86 | * @param code 数据库中存储的自定义code属性 |
89 | private EnumStatus locateEnumStatus( int code) { |
90 | for (EnumStatus status : enums) { |
91 | if (status.getCode().equals(Integer.valueOf(code))) { |
95 | throw new IllegalArgumentException( "未知的枚举类型:" + code + ",请核对" + type.getSimpleName()); |
枚举类
04 | public enum EnumStatus { |
09 | private EnumStatus( int code, String description) { |
10 | this .code = new Integer(code); |
11 | this .description = description; |
15 | private String description; |
18 | public Integer getCode() { |
24 | public String getDescription() { |
实体类
08 | private String accountID; |
10 | private String userName; |
12 | private EnumStatus statusDef; //枚举属性,使用mybatis默认转换类 |
14 | private EnumStatus statusOrdinal; //枚举属性,使用EnumOrdinalTypeHandler转换 |
16 | private EnumStatus statusCustom; // 枚举属性,自定义枚举转换类 |
18 | public String getId() { |
23 | public void setId(String id) { |
28 | public String getAccountID() { |
33 | public void setAccountID(String accountID) { |
34 | this .accountID = accountID; |
38 | public String getUserName() { |
43 | public void setUserName(String userName) { |
44 | this .userName = userName; |
48 | public EnumStatus getStatusDef() { |
52 | public void setStatusDef(EnumStatus statusDef) { |
53 | this .statusDef = statusDef; |
56 | public EnumStatus getStatusOrdinal() { |
60 | public void setStatusOrdinal(EnumStatus statusOrdinal) { |
61 | this .statusOrdinal = statusOrdinal; |
64 | public EnumStatus getStatusCustom() { |
68 | public void setStatusCustom(EnumStatus statusCustom) { |
69 | this .statusCustom = statusCustom; |
73 | public String toString() { |
74 | StringBuffer str = new StringBuffer(); |
79 | str.append( "userName:" ); |
83 | str.append( "statusDef:" ); |
84 | str.append(statusDef.name()); |
87 | str.append( "statusOrdinal:" ); |
88 | str.append(statusOrdinal.name()); |
91 | str.append( "statusCustom:" ); |
92 | str.append(statusCustom.name()); |
95 | return str.toString(); |
mybatis配置文件
01 | <? xml version = "1.0" encoding = "UTF-8" ?> |
03 | PUBLIC "-////DTD Mapper 3.0//EN" |
05 | < mapper namespace = "com.sg.bean.User" > |
07 | < resultMap type = "User" id = "userMap" > |
08 | < id column = "id" property = "id" /> |
09 | < result column = "accountID" property = "accountID" /> |
10 | < result column = "userName" property = "userName" /> |
11 | < result column = "statusDef" property = "statusDef" /> |
12 | < result column = "statusOrdinal" property = "statusOrdinal" typeHandler = "org.apache.ibatis.type.EnumOrdinalTypeHandler" /> |
13 | < result column = "statusCustom" property = "statusCustom" typeHandler = "com.sg.util.typehandler.EnumStatusHandler" /> |
16 | < select id = "selectUser" resultMap = "userMap" > |
17 | select * from t_user where id = #{id} |
20 | < insert id = "insertUser" parameterType = "User" > |
21 | insert into t_user(id,accountID,userName,statusDef,statusOrdinal,statusCustom) |
23 | #{id}, #{accountID}, #{userName}, |
25 | #{statusOrdinal, typeHandler=org.apache.ibatis.type.EnumOrdinalTypeHandler}, |
26 | #{statusCustom, typeHandler=com.sg.util.typehandler.EnumStatusHandler} |
数据库脚本
2 | `id` varchar (45) NOT NULL , |
3 | `accountID` varchar (45) DEFAULT NULL , |
4 | `userName` varchar (45) DEFAULT NULL , |
5 | `statusDef` varchar (45) DEFAULT NULL , |
6 | `statusOrdinal` varchar (45) DEFAULT NULL , |
7 | `statusCustom` int (11) DEFAULT NULL , |
9 | ) ENGINE=InnoDB DEFAULT CHARSET=utf8 COMMENT= '用户表' ; |
|