平时咱们写程序实体类内或多或少都会有枚举类型属性,方便嘛。但是mybatis里怎么处理他们的增删改查呢?
要求:
插入的时候,会用枚举的定义插入数据库,我们希望在数据库中看到的是数字或者其他东西;
查询的时候,数据库的值可以自动转换为我们对应的枚举值。
举例,我有一个这样的枚举类型:
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:
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.hekliu.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 2018, update_time=Mon Jan 26 21:17:09 CST 2018]]
完美结果。