zoukankan      html  css  js  c++  java
  • MyBatis对于Java对象里的枚举类型处理

    平时咱们写程序实体类内或多或少都会有枚举类型属性,方便嘛。但是mybatis里怎么处理他们的增删改查呢?

    要求:

    插入的时候,会用枚举的定义插入数据库,我们希望在数据库中看到的是数字或者其他东西;

    查询的时候,数据库的值可以自动转换为我们对应的枚举值。

    举例,我有一个这样的枚举类型:

    Java Code复制内容到剪贴板
    1. package cn.com.shuyangyang.domain;  
    2.   
    3. public enum UserStatus {  
    4.   
    5.     /** 无效*/  
    6.     DISABLED(0),  
    7.     /** 有效 */  
    8.     AVAILABLE(1);  
    9.       
    10.     private int status;  
    11.       
    12.     UserStatus(int status){  
    13.         this.status = status;  
    14.     }  
    15.   
    16.     public int getStatus() {  
    17.         return status;  
    18.     }  
    19.       
    20. }  

    我们插入数据库中,数据库应该为我们保存0或者1

    我们可以使用mybatis自带的枚举类型EnumOrdinalTypeHandler

    举例如下:

    Java Code复制内容到剪贴板
    1. <insert id="addUser" parameterType="User">  
    2.     INSERT INTO t_user(USER_ID,USER_NAME,LOGIN_NAME,  
    3.     LOGIN_PASSWORD,USER_STATUS,CREATE_TIME,UPDATE_TIME)  
    4.     VALUES(  
    5.         #{user_id},  
    6.         #{user_name},  
    7.         #{login_name},  
    8.         #{login_password},  
    9.         #{user_status, typeHandler=org.apache.ibatis.type.EnumOrdinalTypeHandler},  
    10.         #{create_time},  
    11.         #{update_time}  
    12.     )  
    13. </insert>  

    我们的UserStatus插入的时候是UserStatus.AVAILABLE

    执行完毕后,看结果:

    DB.jpg

    看,是不是结果是我们期望的那样。

    但是问题来了?

    我们查询的时候报错了:Error querying database.  Cause: java.lang.IllegalArgumentException: No enum constant cn.com.shuyangyang.mybatis.UserStatus.1

    我们可以自定义这样的一个EnumStatusHandler:

    Java Code复制内容到剪贴板
    1. package cn.com.shuyangyang.mybatis;  
    2.   
    3. import java.sql.CallableStatement;  
    4. import java.sql.PreparedStatement;  
    5. import java.sql.ResultSet;  
    6. import java.sql.SQLException;  
    7.   
    8. import org.apache.ibatis.type.BaseTypeHandler;  
    9. import org.apache.ibatis.type.JdbcType;  
    10.   
    11. /** 
    12.  * Mybatis自定义转换类型 
    13.  * @author ShuYangYang 
    14.  * E-Mail:shuyangyang@aliyun.com 
    15.  * http://www.shuyangyang.com.cn 
    16.  * Date:2015年1月26日下午10:12:54 
    17.  * 
    18.  */  
    19. public class EnumStatusHandler extends BaseTypeHandler<UserStatus> {  
    20.       
    21.     private Class<UserStatus> type;  
    22.        
    23.     private final UserStatus[] enums;  
    24.    
    25.     /** 
    26.      * 设置配置文件设置的转换类以及枚举类内容,供其他方法更便捷高效的实现 
    27.      * @param type 配置文件中设置的转换类 
    28.      */  
    29.     public EnumStatusHandler(Class<UserStatus> type) {  
    30.         if (type == null)  
    31.             throw new IllegalArgumentException("Type argument cannot be null");  
    32.         this.type = type;  
    33.         this.enums = type.getEnumConstants();  
    34.         if (this.enums == null)  
    35.             throw new IllegalArgumentException(type.getSimpleName()  
    36.                     + " does not represent an enum type.");  
    37.     }  
    38.   
    39.     @Override  
    40.     public void setNonNullParameter(PreparedStatement ps, int i,  
    41.             UserStatus parameter, JdbcType jdbcType) throws SQLException {  
    42.         // baseTypeHandler已经帮我们做了parameter的null判断  
    43.         ps.setInt(i, parameter.getStatus());  
    44.           
    45.     }  
    46.   
    47.     @Override  
    48.     public UserStatus getNullableResult(ResultSet rs, String columnName)  
    49.             throws SQLException {  
    50.         // 根据数据库存储类型决定获取类型,本例子中数据库中存放INT类型  
    51.         int i = rs.getInt(columnName);  
    52.            
    53.         if (rs.wasNull()) {  
    54.             return null;  
    55.         } else {  
    56.             // 根据数据库中的code值,定位EnumStatus子类  
    57.             return locateEnumStatus(i);  
    58.         }  
    59.     }  
    60.   
    61.     @Override  
    62.     public UserStatus getNullableResult(ResultSet rs, int columnIndex)  
    63.             throws SQLException {  
    64.         // 根据数据库存储类型决定获取类型,本例子中数据库中存放INT类型  
    65.         int i = rs.getInt(columnIndex);  
    66.         if (rs.wasNull()) {  
    67.             return null;  
    68.         } else {  
    69.             // 根据数据库中的code值,定位EnumStatus子类  
    70.             return locateEnumStatus(i);  
    71.         }  
    72.     }  
    73.   
    74.     @Override  
    75.     public UserStatus getNullableResult(CallableStatement cs, int columnIndex)  
    76.             throws SQLException {  
    77.         // 根据数据库存储类型决定获取类型,本例子中数据库中存放INT类型  
    78.         int i = cs.getInt(columnIndex);  
    79.         if (cs.wasNull()) {  
    80.             return null;  
    81.         } else {  
    82.             // 根据数据库中的code值,定位EnumStatus子类  
    83.             return locateEnumStatus(i);  
    84.         }  
    85.     }  
    86.       
    87.     /** 
    88.      * 枚举类型转换,由于构造函数获取了枚举的子类enums,让遍历更加高效快捷 
    89.      * @param code 数据库中存储的自定义code属性 
    90.      * @return code对应的枚举类 
    91.      */  
    92.     private UserStatus locateEnumStatus(int code) {  
    93.         for(UserStatus status : enums) {  
    94.             if(status.getStatus()==(Integer.valueOf(code))) {  
    95.                 return status;  
    96.             }  
    97.         }  
    98.         throw new IllegalArgumentException("未知的枚举类型:" + code + ",请核对" + type.getSimpleName());  
    99.     }  
    100.   
    101. }  

    mapper.xml里这样配置:

    XML/HTML Code复制内容到剪贴板
    1. <resultMap type="User" id="userResult">  
    2. ……省略其他属性配置  
    3.         <result column="USER_STATUS" property="user_status" typeHandler="cn.com.shuyangyang.mybatis.EnumStatusHandler"/>  
    4. ……省略其他属性配置  
    5.     </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]]

     

    完美结果。






  • 相关阅读:
    【转】Java中super和this的几种用法与区别
    公寓上网新认证方式破解研究
    移动设计
    破解哈工程大学深澜认证路由器
    Arch Linux安装记录
    foreach新解
    工具大全(转载)
    Linux 入门
    设置为驼峰命名
    efcore Add-Migration 错误
  • 原文地址:https://www.cnblogs.com/jeffen/p/6380724.html
Copyright © 2011-2022 走看看