mybatis自定义typeHandler

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

@Data
public class Handler implements POJO {

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

  private Set users;

  private Set groups;

}

在mybatis的xml文件中有如下的映射关系


	
        
    

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 extends BaseTypeHandler {

  @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 {

}

另外我们还可以实现下面两种场景,比如我有一个Java中的Date数据类型,我想将之存到数据库的时候存成一个1970年至今的毫秒数,怎么实现?再比如我有一个User类,User类中有一个属性叫做interest,这个属性用来描述用户的爱好,它的数据类型是一个List集合,那么我想在把这个List集合存入数据库的时候能够自动的变成{XXX,XXX,XXX}这样一个字符串然后存起来,当我从数据库读取的时候也是读取到这样一个字符串,读取成功之后再自动的将之转为一个List集合

1:日期转换

@MappedJdbcTypes({JdbcType.VARCHAR})
@MappedTypes({Date.class})
public class MyDateTypeHandler extends BaseTypeHandler {
    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的时候我们指定了javaType和jdbcType,同时也指定了处理的typeHandler,然后在select中使用这个resultMap:

但是这种方式有一个缺点那就是只适用于查询操作,即在查询的过程中系统会启用我们自定义的typeHandler,会将秒数转为Date对象,但是在插入的时候却不会启用我们自定义的typeHandler,想要在插入的时候启用自定义的typeHandler,需要我们在insert节点中简单配置一下,如下:


        INSERT INTO user4(username,password,regTime) VALUES (#{username},#{password},#{regTime,javaType=Date,jdbcType=VARCHAR,typeHandler=org.sang.db.MyDateTypeHandler})
    

也可以只配置javaType和jdbcType,如下:


        INSERT INTO user4(username,password,regTime) VALUES (#{username},#{password},#{regTime,javaType=Date,jdbcType=VARCHAR})
    

或者只配置typeHandler:


        INSERT INTO user4(username,password,regTime) VALUES (#{username},#{password},#{regTime,typeHandler=com.db.MyDateTypeHandler})
    
这三种效果都是一样的,都是在插入的时候将数据Date对象转为秒数


2:List集合的转换

@MappedTypes(List.class)
@MappedJdbcTypes({JdbcType.VARCHAR})
public class MyListTypeHandler extends BaseTypeHandler> {
    public void setNonNullParameter(PreparedStatement preparedStatement, int i, List 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 getNullableResult(ResultSet resultSet, String s) throws SQLException {
        String[] split = resultSet.getString(s).split(",");
        return Arrays.asList(split);
    }

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

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

查询:

插入:


        INSERT INTO person(interest) VALUES (#{interest,typeHandler=com.db.MyListTypeHandler})

List集合存入数据库之后变成这样: 


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

mybatis自定义typeHandler_第1张图片


你可能感兴趣的:(java)