ibatis对枚举类的支持

原创
2013/11/28 22:32
阅读数 2.7K
    前一段时间和同事争论枚举类是否该出现在pojo类中,当时出现了分歧。因为项目中使用ibatis,我认为枚举类在get、set方法中需要进行特殊处理,破坏了原有的pojo纯净。后来我发现我错了:pojo类中可以存放,并且最好使用枚举。

pojo类

package com.sg.bean;

public class User {

    /**
     * 用户ID
     */
    private String userID;
    
    /**
     * 用户名 
     */
    private String userName;
    
    /**
     * 用户状态
     * @see com.sg.bean.EnumStatus
     */
    private EnumStatus status;
    
    public String getUserID() {
        return userID;
    }
    public void setUserID(String userID) {
        this.userID = userID;
    }
    public String getUserName() {
        return userName;
    }
    public void setUserName(String userName) {
        this.userName = userName;
    }
    public EnumStatus getStatus() {
        return status;
    }
    public void setStatus(EnumStatus status) {
        this.status = status;
    }
}


枚举类


package com.sg.bean;

public enum EnumStatus {

    NORMAL("1", "正常"),
    DELETE("2", "删除"),
    LOGICDEL("3", "注销");
    
    private EnumStatus(String code, String description) {
        this.code = code;
        this.description = description;
    }
    private String code;
    
    private String description;

    public String getCode() {
        return code;
    }

    public void setCode(String code) {
        this.code = code;
    }

    public String getDescription() {
        return description;
    }

    public void setDescription(String description) {
        this.description = description;
    }
}



重点来了——ibatis类型转换接口实现



先看一下源码中的注释

com.ultrapower.common.ibatis.sqlmap.client.extensions.TypeHandlerCallback
A simple interface for implementing custom type handlers. 

Using this interface, you can implement a type handler that will perform customized processing before parameters are set on a PreparedStatement and after values are retrieved from a ResultSet. Using a custom type handler you can extend the framework to handle types that are not supported, or handle supported types in a different way. For example, you might use a custom type handler to implement proprietary BLOB support (e.g. Oracle), or you might use it to handle booleans using "Y" and "N" instead of the more typical 0/1. 

EXAMPLE 

Here's a simple example of a boolean handler that uses "Yes" and "No". 


 public class YesNoBoolTypeHandlerCallback implements TypeHandlerCallback {
 <p/>
   private static final String YES = "Yes";
   private static final String NO = "No";
 <p/>
   public Object getResult(ResultGetter getter) throws SQLException {
     String s = getter.getString();
     if (YES.equalsIgnoreCase(s)) {
       return new Boolean (true);
     } else if (NO.equalsIgnoreCase(s)) {
       return new Boolean (false);
     } else {
       throw new SQLException ("Unexpected value " + s + " found where "+YES+" or "+NO+" was expected.");
     }
   }
 <p/>
   public void setParameter(ParameterSetter setter, Object parameter) throws SQLException {
     boolean b = ((Boolean)parameter).booleanValue();
     if (b) {
       setter.setString(YES);
     } else {
       setter.setString(NO);
     }
   }
 <p/>
   public Object valueOf(String s) {
     if (YES.equalsIgnoreCase(s)) {
       return new Boolean (true);
     } else if (NO.equalsIgnoreCase(s)) {
       return new Boolean (false);
     } else {
       throw new SQLException ("Unexpected value " + s + " found where "+YES+" or "+NO+" was expected.");
     }
   }
 <p/>
 }



针对User对象中的EnumStatus,他的转换类如下



package com.sg.util;

import java.sql.SQLException;
import java.sql.Types;

import com.ibatis.sqlmap.client.extensions.ParameterSetter;
import com.ibatis.sqlmap.client.extensions.ResultGetter;
import com.ibatis.sqlmap.client.extensions.TypeHandlerCallback;
import com.sg.bean.EnumStatus;

public class EnumStatusHandler implements TypeHandlerCallback {

    public Object getResult(ResultGetter getter) throws SQLException {
        EnumStatus result = null;
        if(!getter.wasNull() && getter.getObject()!= null) {
            for(EnumStatus status : EnumStatus.values()) {
                if(status.getCode().equals(getter.getObject())) {
                    result = status;
                    break;
                }
            }
        }
        return result;
    }

    public void setParameter(ParameterSetter setter, Object obj)
            throws SQLException {
        if(obj == null) {
            setter.setInt(Types.INTEGER);
        }else {
            EnumStatus status = (EnumStatus)obj;
            setter.setString(status.getCode());
        }
    }

    public Object valueOf(String s) {
        return s;
    }

}






ibatis配置文件声明

<?xml version="1.0" encoding="UTF-8" ?>
<!DOCTYPE sqlMapConfig 
PUBLIC "-//iBATIS.com//DTD SQL Map Config 2.0//EN" "http://ibatis.apache.org/dtd/sql-map-config-2.dtd">
<sqlMapConfig>
	<settings cacheModelsEnabled="true" enhancementEnabled="true"
		lazyLoadingEnabled="true" errorTracingEnabled="true" maxRequests="32"
		maxSessions="10" maxTransactions="5" useStatementNamespaces="false" />
		
	<typeAlias alias="com.sg.bean.EnumStatus" type="com.sg.util.EnumStatusHandler"/>
	
	<transactionManager type="JDBC">
		<dataSource type="SIMPLE">
			<property name="JDBC.Driver" value="com.mysql.jdbc.Driver" />
			<property name="JDBC.ConnectionURL"
				value="jdbc:mysql://localhost:3306/sg" />
			<property name="JDBC.Username" value="root" />
			<property name="JDBC.Password" value="root" />
			<property name="Pool.MaximumIdleConnections" value="5" />
			<property name="Pool.MaximumCheckoutTime" value="120000" />
			<property name="Pool.TimeToWait" value="500" />
			<property name="Pool.PingQuery"
				value="select 1 from sample" />
			<property name="Pool.PingEnabled" value="false" />
			<property name="Pool.PingConnectionsOlderThan" value="1" />
			<property name="Pool.PingConnectionsNotUsedFor" value="1" />
		</dataSource>
	</transactionManager>
	
	<sqlMap resource="User.xml" />
</sqlMapConfig>



    经过上述的配置,User对象中的EnumStatus枚举类就可以顺利的进行数据库操作了,以上方案有以下几个好处:



  1. 没有破坏pojo的纯净,pojo对象的扩展和可维护性更高;
  2. 枚举类加强了User对象对属性类型的把控,开发这不用担心其他人在status属性中放错值了;
  3. pojo的扩展性增强,比如现在前台展示需要展示名称,开发者只需对枚举进行简单的读取就可以将数据库中的0、1转为自然语言;
  4. 脱离实体的限制,比如前台需要展示status的可选值,枚举类便可以首当其冲。



展开阅读全文
打赏
0
22 收藏
分享
加载中
推荐国内最流行的ibatis代码生成网站 --- fwjava.com
无需任何安装配置,直接在线生成,且十分规范好用.
现在,很多知名的互联网公司都在用它.
2016/09/20 18:49
回复
举报

引用来自“cloudroc”的评论

选择数据字典比较好
有没有相关资料
2014/08/07 11:15
回复
举报
选择数据字典比较好
2014/01/06 21:59
回复
举报
磐谷博主

引用来自“xmut”的评论

这种方法很早就有人用了,关键是一种枚举类型要写一个TypeHandler,一个项目有那么多枚举类型,楼主不觉得要崩溃吗?262626

这是一个问题,我打算用“约定”的方式管理:统一包、统一TypeHandler名称来管理。
2013/12/01 22:04
回复
举报
这种方法很早就有人用了,关键是一种枚举类型要写一个TypeHandler,一个项目有那么多枚举类型,楼主不觉得要崩溃吗?262626
2013/11/30 20:06
回复
举报
我就发现这一个bug啊,呵呵!你们遇到过没?
2013/11/29 15:06
回复
举报
磐谷博主

引用来自“宅男小何”的评论

引用来自“闫磊”的评论

引用来自“宅男小何”的评论

ibatis都没人维护了哦

嗯,没错,但是我们的项目还用49

我们项目也在用,我前段时间还提了一个bug,可惜没人fixed 了https://github.com/mybatis/mybatis-2/issues

还有其他的问题吗?如果能收集足够多的证据,我就有理由推动组件升级了。
2013/11/29 14:51
回复
举报

引用来自“闫磊”的评论

引用来自“宅男小何”的评论

ibatis都没人维护了哦

嗯,没错,但是我们的项目还用49

我们项目也在用,我前段时间还提了一个bug,可惜没人fixed 了https://github.com/mybatis/mybatis-2/issues
2013/11/29 14:42
回复
举报
磐谷博主

引用来自“宅男小何”的评论

ibatis都没人维护了哦

嗯,没错,但是我们的项目还用49
2013/11/29 14:12
回复
举报
ibatis都没人维护了哦
2013/11/29 13:56
回复
举报
更多评论
打赏
13 评论
22 收藏
0
分享
返回顶部
顶部