專欄:深刻理解MyBatis原理 - 博客頻道 - CSDN.NETjava
--------------------------------------------------------------------------------sql
摘要: mybatis自定義枚舉轉換類的實現示例。數據庫
mybatis提供了EnumTypeHandler和EnumOrdinalTypeHandler完成枚舉類型的轉換,二者的功能已經基本知足了平常的使用。可是可能有這樣的需求:因爲某種緣由,咱們不想使用枚舉的name和ordinal做爲數據存儲字段。mybatis的自定義轉換類出現了。apache
1. mybatis廢棄了ibatis的TypeHandlerCallback接口,取而代之的接口是TypeHandler,它與原來的接口略有不一樣,可是方法相似。(見說明 https://code.google.com/p/mybatis/wiki/DocUpgrade3)mybatis
2. BaseTypeHandler是mybatis提供的基礎轉換類,該類實現了TypeHandler接口並提供不少公用方法,建議每一個自定義轉換類都繼承它。app
使用一段代碼,將枚舉類EnumStatus中的code屬性存儲到數據庫對應字段statusCustom。ide
package com.sg.util.typehandler; import java.sql.CallableStatement; import java.sql.PreparedStatement; import java.sql.ResultSet; import java.sql.SQLException; import org.apache.ibatis.type.BaseTypeHandler; import org.apache.ibatis.type.JdbcType; import com.sg.bean.EnumStatus; /** * 自定義EnumStatus轉換類 <br> * 存儲屬性:EnumStatus.getCode() <br> * JDBCType:INT * @author yanlei */ public class EnumStatusHandler extends BaseTypeHandler<EnumStatus> { private Class<EnumStatus> type; private final EnumStatus[] enums; /** * 設置配置文件設置的轉換類以及枚舉類內容,供其餘方法更便捷高效的實現 * @param type 配置文件中設置的轉換類 */ public EnumStatusHandler(Class<EnumStatus> 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 EnumStatus getNullableResult(ResultSet rs, String columnName) throws SQLException { // 根據數據庫存儲類型決定獲取類型,本例子中數據庫中存放INT類型 int i = rs.getInt(columnName); if (rs.wasNull()) { return null; } else { // 根據數據庫中的code值,定位EnumStatus子類 return locateEnumStatus(i); } } @Override public EnumStatus getNullableResult(ResultSet rs, int columnIndex) throws SQLException { // 根據數據庫存儲類型決定獲取類型,本例子中數據庫中存放INT類型 int i = rs.getInt(columnIndex); if (rs.wasNull()) { return null; } else { // 根據數據庫中的code值,定位EnumStatus子類 return locateEnumStatus(i); } } @Override public EnumStatus getNullableResult(CallableStatement cs, int columnIndex) throws SQLException { // 根據數據庫存儲類型決定獲取類型,本例子中數據庫中存放INT類型 int i = cs.getInt(columnIndex); if (cs.wasNull()) { return null; } else { // 根據數據庫中的code值,定位EnumStatus子類 return locateEnumStatus(i); } } @Override public void setNonNullParameter(PreparedStatement ps, int i, EnumStatus parameter, JdbcType jdbcType) throws SQLException { // baseTypeHandler已經幫咱們作了parameter的null判斷 ps.setInt(i, parameter.getCode()); } /** * 枚舉類型轉換,因爲構造函數獲取了枚舉的子類enums,讓遍歷更加高效快捷 * @param code 數據庫中存儲的自定義code屬性 * @return code對應的枚舉類 */ private EnumStatus locateEnumStatus(int code) { for(EnumStatus status : enums) { if(status.getCode().equals(Integer.valueOf(code))) { return status; } } throw new IllegalArgumentException("未知的枚舉類型:" + code + ",請覈對" + type.getSimpleName()); } }
package com.sg.bean; public enum EnumStatus { NORMAL(1, "正常"), DELETE(0, "刪除"), CANCEL(2, "註銷"); private EnumStatus(int code, String description) { this.code = new Integer(code); this.description = description; } private Integer code; private String description; public Integer getCode() { return code; } public String getDescription() { return description; } }
package com.sg.bean; public class User { private String id; private String accountID; private String userName; private EnumStatus statusDef; //枚舉屬性,使用mybatis默認轉換類 private EnumStatus statusOrdinal; //枚舉屬性,使用EnumOrdinalTypeHandler轉換 private EnumStatus statusCustom; // 枚舉屬性,自定義枚舉轉換類 public String getId() { return id; } public void setId(String id) { this.id = id; } public String getAccountID() { return accountID; } public void setAccountID(String accountID) { this.accountID = accountID; } public String getUserName() { return userName; } public void setUserName(String userName) { this.userName = userName; } public EnumStatus getStatusDef() { return statusDef; } public void setStatusDef(EnumStatus statusDef) { this.statusDef = statusDef; } public EnumStatus getStatusOrdinal() { return statusOrdinal; } public void setStatusOrdinal(EnumStatus statusOrdinal) { this.statusOrdinal = statusOrdinal; } public EnumStatus getStatusCustom() { return statusCustom; } public void setStatusCustom(EnumStatus statusCustom) { this.statusCustom = statusCustom; } @Override public String toString() { StringBuffer str = new StringBuffer(); str.append("id:"); str.append(id); str.append("\n"); str.append("userName:"); str.append(userName); str.append("\n"); str.append("statusDef:"); str.append(statusDef.name()); str.append("\n"); str.append("statusOrdinal:"); str.append(statusOrdinal.name()); str.append("\n"); str.append("statusCustom:"); str.append(statusCustom.name()); str.append("\n"); return str.toString(); } }
<?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.sg.bean.User"> <resultMap type="User" id="userMap"> <id column="id" property="id"/> <result column="accountID" property="accountID"/> <result column="userName" property="userName"/> <result column="statusDef" property="statusDef"/> <result column="statusOrdinal" property="statusOrdinal" typeHandler="org.apache.ibatis.type.EnumOrdinalTypeHandler"/> <result column="statusCustom" property="statusCustom" typeHandler="com.sg.util.typehandler.EnumStatusHandler"/> </resultMap> <select id="selectUser" resultMap="userMap"> select * from t_user where id = #{id} </select> <insert id="insertUser" parameterType="User"> insert into t_user(id,accountID,userName,statusDef,statusOrdinal,statusCustom) values( #{id}, #{accountID}, #{userName}, #{statusDef}, #{statusOrdinal, typeHandler=org.apache.ibatis.type.EnumOrdinalTypeHandler}, #{statusCustom, typeHandler=com.sg.util.typehandler.EnumStatusHandler} ) </insert> </mapper>
數據庫腳本函數
CREATE TABLE `t_user` ( `id` varchar(45) NOT NULL, `accountID` varchar(45) DEFAULT NULL, `userName` varchar(45) DEFAULT NULL, `statusDef` varchar(45) DEFAULT NULL, `statusOrdinal` varchar(45) DEFAULT NULL, `statusCustom` int(11) DEFAULT NULL, PRIMARY KEY (`id`) ) ENGINE=InnoDB DEFAULT CHARSET=utf8 COMMENT='用戶表';