您的位置:首页 > 其它

mybatis自定义typeHandler

2018-03-02 10:00 309 查看
在做开发的时候,经常会遇到关于数据类型的问题,mybatis本身已经为我们提供了许多typeHandler了,系统提供的typeHandler能够满足我们日常开发中的大部分需求,但是有时候也会遇到需要自己定义typeHandler的情况,比如说我在数据库中有一个WfWorkSpace表,其中有一个字段Handler记录了当前处理人的信息,在数据库中改字段类型是varchar,但是在java代码中这个Handler的数据结构是一个实体类,如下所示:@Data
public class Handler implements POJO {

/**
*
*/
private static final long serialVersionUID = 1L;

private Set<UserLink> users;

private Set<GroupLink> groups;

}在mybatis的xml文件中有如下的映射关系<resultMap type="com..entity.WfWorkSpace" id="wfWorkSpaceMap">
<result column="ID" jdbcType="NUMERIC" property="id" />
<result column="HANDLER" jdbcType="VARCHAR" property="handler" />

</resultMap>WfWorkSpace实体类为:public class WfWorkSpace extends LongIdVO {

/**
*
*/
private static final long serialVersionUID = -5555413588381268957L;

private Long id;

private Handler handler;这个时候就需要涉及到自定义一个mybatis的typeHandler问题了

自定义typeHandler继承自BaseTypeHandler

第一步,实现一个集成自BaseTypeHandler的公共数据格式处理的类JsonTypeHandler:public class JsonTypeHandler<T> extends BaseTypeHandler<T> {

@Override
public void setNonNullParameter(PreparedStatement ps, int i, T parameter, JdbcType jdbcType)
throws SQLException {
ps.setString(i, JSON.toJSONString(parameter));
}

@Override
public T getNullableResult(ResultSet rs, String columnName) throws SQLException {
return JSON.parseObject(rs.getString(columnName), getRawType());
}

@Override
public T getNullableResult(ResultSet rs, int columnIndex) throws SQLException {
return JSON.parseObject(rs.getString(columnIndex), getRawType());
}

@Override
public T getNullableResult(CallableStatement cs, int columnIndex) throws SQLException {
return JSON.parseObject(cs.getString(columnIndex), getRawType());
}
}第二步,自定义TypeHandler类型:@Component
@MappedTypes(Handler.class)
public class HandlerTypeHandler extends JsonTypeHandler<Handler> {

}另外我们还可以实现下面两种场景,比如我有一个Java中的Date数据类型,我想将之存到数据库的时候存成一个1970年至今的毫秒数,怎么实现?再比如我有一个User类,User类中有一个属性叫做interest,这个属性用来描述用户的爱好,它的数据类型是一个List集合,那么我想在把这个List集合存入数据库的时候能够自动的变成
{XXX,XXX,XXX}
这样一个字符串然后存起来,当我从数据库读取的时候也是读取到这样一个字符串,读取成功之后再自动的将之转为一个List集合
1:日期转换@MappedJdbcTypes({JdbcType.VARCHAR})
@MappedTypes({Date.class})
public class MyDateTypeHandler extends BaseTypeHandler<Date> {
public void setNonNullParameter(PreparedStatement preparedStatement, int i, Date date, JdbcType jdbcType) throws SQLException {
preparedStatement.setString(i, String.valueOf(date.getTime()));
}

public Date getNullableResult(ResultSet resultSet, String s) throws SQLException {
return new Date(resultSet.getLong(s));
}

public Date getNullableResult(ResultSet resultSet, int i) throws SQLException {
return new Date(resultSet.getLong(i));
}

public Date getNullableResult(CallableStatement callableStatement, int i) throws SQLException {
return callableStatement.getDate(i);
}
}自定义好了typeHandler之后,接下来我们需要在userMapper.xml中进行简单的配置,首先我们可以像上文说的,配置resultMap,如下:
<resultMap id="userResultMap" type="com.bean.User">
<result typeHandler="com.db.MyDateTypeHandler" column="regTime" javaType="java.util.Date"
jdbcType="VARCHAR"
property="regTime"/>
</resultMap>配置resultMap的时候我们指定了javaType和jdbcType,同时也指定了处理的typeHandler,然后在select中使用这个resultMap:
<select id="getUser" resultMap="userResultMap">
select * from user4
</select>但是这种方式有一个缺点那就是只适用于查询操作,即在查询的过程中系统会启用我们自定义的typeHandler,会将秒数转为Date对象,但是在插入的时候却不会启用我们自定义的typeHandler,想要在插入的时候启用自定义的typeHandler,需要我们在insert节点中简单配置一下,如下:<insert id="insertUser" parameterType="org.sang.bean.User">
INSERT INTO user4(username,password,regTime) VALUES (#{username},#{password},#{regTime,javaType=Date,jdbcType=VARCHAR,typeHandler=org.sang.db.MyDateTypeHandler})
</insert>也可以只配置javaType和jdbcType,如下:<insert id="insertUser2">
INSERT INTO user4(username,password,regTime) VALUES (#{username},#{password},#{regTime,javaType=Date,jdbcType=VARCHAR})
</insert>或者只配置typeHandler:<insert id="insertUser3">
INSERT INTO user4(username,password,regTime) VALUES (#{username},#{password},#{regTime,typeHandler=com.db.MyDateTypeHandler})
</insert>这三种效果都是一样的,都是在插入的时候将数据Date对象转为秒数

2:List集合的转换@MappedTypes(List.class)
@MappedJdbcTypes({JdbcType.VARCHAR})
public class MyListTypeHandler extends BaseTypeHandler<List<String>> {
public void setNonNullParameter(PreparedStatement preparedStatement, int i, List<String> strings, JdbcType jdbcType) throws SQLException {
//1.List集合转字符串
StringBuffer sb = new StringBuffer();
for (String string : strings) {
sb.append(string).append(",");
}
//2.设置给ps
preparedStatement.setString(i, sb.toString().substring(0, sb.toString().length() - 1));
}

public List<String> getNullableResult(ResultSet resultSet, String s) throws SQLException {
String[] split = resultSet.getString(s).split(",");
return Arrays.asList(split);
}

public List<String> getNullableResult(ResultSet resultSet, int i) throws SQLException {
String[] split = resultSet.getString(i).split(",");
return Arrays.asList(split);
}

public List<String> getNullableResult(CallableStatement callableStatement, int i) throws SQLException {
String[] split = callableStatement.getString(i).split(",");
return Arrays.asList(split);
}
}查询:<select id="getPerson" resultType="com.bean.Person">
select * from person
</select>插入:<insert id="insertPerson">
INSERT INTO
4000
person(interest) VALUES (#{interest,typeHandler=com.db.MyListTypeHandler})
</insert>List集合存入数据库之后变成这样: 



读取出来之后又自动转为List集合了,下图是查询操作,实体类,和查询结果: 

内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息