平時咱們寫程序實體類內或多或少都會有枚舉類型屬性,方便嘛。但是mybatis里怎么處理他們的增刪改查呢?
要求:
插入的時候,會用枚舉的定義插入數據庫,我們希望在數據庫中看到的是數字或者其他東西;
查詢的時候,數據庫的值可以自動轉換為我們對應的枚舉值。
舉例,我有一個這樣的枚舉類型:
- package cn.com.shuyangyang.domain;
- public enum UserStatus {
- /** 無效*/
- DISABLED(0),
- /** 有效 */
- AVAILABLE(1);
- private int status;
- UserStatus(int status){
- this.status = status;
- }
- public int getStatus() {
- return status;
- }
- }
我們插入數據庫中,數據庫應該為我們保存0或者1
我們可以使用mybatis自帶的枚舉類型EnumOrdinalTypeHandler
舉例如下:
- <insert id="addUser" parameterType="User">
- INSERT INTO t_user(USER_ID,USER_NAME,LOGIN_NAME,
- LOGIN_PASSWORD,USER_STATUS,CREATE_TIME,UPDATE_TIME)
- VALUES(
- #{user_id},
- #{user_name},
- #{login_name},
- #{login_password},
- #{user_status, typeHandler=org.apache.ibatis.type.EnumOrdinalTypeHandler},
- #{create_time},
- #{update_time}
- )
- </insert>
我們的UserStatus插入的時候是UserStatus.AVAILABLE
執行完畢后,看結果:
看,是不是結果是我們期望的那樣。
但是問題來了?
我們查詢的時候報錯了:Error querying database. Cause: java.lang.IllegalArgumentException: No enum constant cn.com.shuyangyang.mybatis.UserStatus.1
我們可以自定義這樣的一個EnumStatusHandler:
- package cn.com.shuyangyang.mybatis;
- 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;
- /**
- * Mybatis自定義轉換類型
- * @author ShuYangYang
- * E-Mail:shuyangyang@aliyun.com
- * http://www.shuyangyang.com.cn
- * Date:2015年1月26日下午10:12:54
- *
- */
- public class EnumStatusHandler extends BaseTypeHandler<UserStatus> {
- private Class<UserStatus> type;
- private final UserStatus[] enums;
- /**
- * 設置配置文件設置的轉換類以及枚舉類內容,供其他方法更便捷高效的實現
- * @param type 配置文件中設置的轉換類
- */
- public EnumStatusHandler(Class<UserStatus> 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 void setNonNullParameter(PreparedStatement ps, int i,
- UserStatus parameter, JdbcType jdbcType) throws SQLException {
- // baseTypeHandler已經幫我們做了parameter的null判斷
- ps.setInt(i, parameter.getStatus());
- }
- @Override
- public UserStatus 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 UserStatus 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 UserStatus getNullableResult(CallableStatement cs, int columnIndex)
- throws SQLException {
- // 根據數據庫存儲類型決定獲取類型,本例子中數據庫中存放INT類型
- int i = cs.getInt(columnIndex);
- if (cs.wasNull()) {
- return null;
- } else {
- // 根據數據庫中的code值,定位EnumStatus子類
- return locateEnumStatus(i);
- }
- }
- /**
- * 枚舉類型轉換,由於構造函數獲取了枚舉的子類enums,讓遍歷更加高效快捷
- * @param code 數據庫中存儲的自定義code屬性
- * @return code對應的枚舉類
- */
- private UserStatus locateEnumStatus(int code) {
- for(UserStatus status : enums) {
- if(status.getStatus()==(Integer.valueOf(code))) {
- return status;
- }
- }
- throw new IllegalArgumentException("未知的枚舉類型:" + code + ",請核對" + type.getSimpleName());
- }
- }
mapper.xml里這樣配置:
- <resultMap type="User" id="userResult">
- ……省略其他屬性配置
- <result column="USER_STATUS" property="user_status" typeHandler="cn.com.shuyangyang.mybatis.EnumStatusHandler"/>
- ……省略其他屬性配置
- </resultMap>
現在來看看結果:
[User [user_id=782cba19-559f-41c3-a1b0-25fcac4cf118, user_name=系統管理員, login_name=admin, login_password=admin,user_status=AVAILABLE, create_time=Mon Jan 26 21:17:09 CST 2015, update_time=Mon Jan 26 21:17:09 CST 2015]]
完美結果。