一、typeHandler 的使用
 
   1、存储json格式字段
 
        如果字段需要存储为json格式,可以使用JacksonTypeHandler处理器。使用方式非常简单,如下所示:
         
        只需要加上两个注解即可:
          @TableName(autoResultMap = true) 表示自动映射resultMap
          @TableField(typeHandler = JacksonTypeHandler.class)表示将UserInfo对象转为json对象入库
        2、自定义 typeHandler 实现类
 
例如当我们 某个字段存储的类型为List或者Map时,我们可以自定义一个TypeHandler,以 list 为例,我们想存储一个字段类型为 list ,在数据库中的存储的格式是 多条数据以逗号分割,当查询时会自动根据逗号分割成列表格式。
        需要实现BaseTypeHandler抽象类:
@MappedJdbcTypes(JdbcType.VARCHAR)
@MappedTypes({List.class})
public class ListTypeHandler extends BaseTypeHandler<List<String>> {
    private static final String DELIM = ",";
    @Override
    public void setNonNullParameter(PreparedStatement preparedStatement, int i, List<String> strings, JdbcType jdbcType) throws SQLException {
        String value = StringUtils.collectionToDelimitedString(strings, DELIM);
        preparedStatement.setString(i, value);
    }
    @Override
    public List<String> getNullableResult(ResultSet resultSet, String s) throws SQLException {
        String value = resultSet.getString(s);
        return Arrays.asList(StringUtils.tokenizeToStringArray(value, DELIM));
    }
    @Override
    public List<String> getNullableResult(ResultSet resultSet, int i) throws SQLException {
        String value = resultSet.getString(i);
        return Arrays.asList(StringUtils.tokenizeToStringArray(value, DELIM));
    }
    @Override
    public List<String> getNullableResult(CallableStatement callableStatement, int i) throws SQLException {
        String value = callableStatement.getString(i);
        return Arrays.asList(StringUtils.tokenizeToStringArray(value, DELIM));
    }
}- @MappedJdbcTypes:表示SQL语句中查出来的类型;
- @MappedTypes:表示要转成 Java 对象的类型;
- DELIM:表示字符串的分隔符,如果你是用空格分开的就赋值为空格。
-  setNonNullParameter(插入时设置参数类型) 
-  getNullableResult(获取时转换回的自定义类型) 
根据列名获取
resultSet:结果集
columnName:列名
public UserInfo getNullableResult(ResultSet resultSet, String columnName)根据索引位置获取
resultSet:结果集
columnIndex:列索引
public UserInfo getNullableResult(ResultSet resultSet, int columnIndex)根据存储过程获取
callableStatement:结果集
columnIndex:列索引
public UserInfo getNullableResult(CallableStatement callableStatement, int columnIndex)然后再字段上指定该实现了即可:
    @TableField(typeHandler = ListTypeHandler.class)
    private List<String> job;        最后在数据库中存储格式为:  
3、存储自定义对象字段
        例如我们刚才使用json格式存储 Unit 字段,如果不加  @TableField(typeHandler = JacksonTypeHandler.class) 就会报错,因为 typeHandler 可以指定我们在Java实体类所包含的自定义类型存入数据库后的类型是什么,也可以从数据库中取出该数据后自动转换为我们自定义的Java类型。
        我们虽然在 Java中定义了 Unit 类型,但是数据库不认识,我们现在就需要将 Unit 转换为数据库认识的类型。Java自带的类型在存取的时候不会出错,我们自定义的类型就会出错 是因为 mybatis已经将这些类型的TypeHandler提前写好了:
                    
所以如果我们要存储 Unit 类型的字段,又不想用 默认的json 格式,我们也需要自定义一个 关于Unit 的 TypeHandler,如下:
public class JsonUtils {
    private static ObjectMapper objectMapper = new ObjectMapper();
    //初始化相关的配置
    static {
        //只引用不为空的值
        objectMapper.setSerializationInclusion(JsonInclude.Include.NON_EMPTY);
        //取消默认转换timestemp
        objectMapper.configure(SerializationFeature.WRITE_DURATIONS_AS_TIMESTAMPS, false);
        //忽略空bean转换错误
        objectMapper.configure(SerializationFeature.FAIL_ON_EMPTY_BEANS, false);
        //忽略在json中存在,在java对象不存在的错误
        objectMapper.configure(DeserializationFeature.FAIL_ON_UNKNOWN_PROPERTIES, false);
        // 解决jackson2无法反序列化LocalDateTime的问题
        objectMapper.disable(SerializationFeature.WRITE_DATES_AS_TIMESTAMPS);
        objectMapper.registerModule(new JavaTimeModule());
    }
    /**
     * 将java对象转换成json字符串
     *
     * @param obj
     * java 对象
     * @param <T>
     * @return
     */
    public static <T> String objectToString(T obj) {
        if (obj == null) {
            return null;
        }
        try {
            return obj instanceof String ? (String) obj : objectMapper.writeValueAsString(obj);
        } catch (JsonProcessingException e) {
            e.printStackTrace();
            return null;
        }
    }
    /**
     * 将json字符串转换成java对象
     *
     * @param json
     * 字符串
     * @param tClass
     * 要转换的对象
     * @param <T>
     * @return
     */
    public static <T> T getObjetFormString(String json, Class<T> tClass) {
        if (StringUtils.isBlank(json) || tClass == null) {
            return null;
        }
        try {
            return tClass.equals(String.class) ? (T) json : objectMapper.readValue(json, tClass);
        } catch (IOException e) {
            e.printStackTrace();
            return null;
        }
    }
    /**
     * 将字符串转换成java对象
     * @param json
     * 字符串
     * @param tTypeReference
     * 对象
     *
     * @param <T>
     * @return
     */
    public static <T> T fromString(String json, TypeReference<T> tTypeReference){
        if (StringUtils.isBlank(json) || tTypeReference == null) {
            return null;
        }
        try {
            return tTypeReference.getType().equals(String.class) ? (T) json : objectMapper.readValue(json, tTypeReference);
        } catch (IOException e) {
            e.printStackTrace();
            return null;
        }
    }
    /**
     * 将json字符串转换成java集合对象
     * @param json
     * 字符串
     * @param collectionClass
     * 集合类型
     * @param elementClazzes
     * 成员类型
     * @param <T>
     * @return
     */
    public static <T> T fromString(String json, Class<?> collectionClass, Class<?> ... elementClazzes){
        JavaType javaType = objectMapper.getTypeFactory().constructParametricType(collectionClass, elementClazzes);
        try {
            return objectMapper.readValue(json, javaType);
        } catch (IOException e) {
            e.printStackTrace();
            return null;
        }
    }
}@MappedTypes(UserInfo.class)
@MappedJdbcTypes(JdbcType.VARCHAR)
public class UserInfoTypeHandler extends BaseTypeHandler<UserInfo> {
    @Override
    public void setNonNullParameter(PreparedStatement preparedStatement, int i, UserInfo userInfo, JdbcType jdbcType) throws SQLException {
        preparedStatement.setString(i,  JsonUtils.objectToString(userInfo));
    }
    @Override
    public UserInfo getNullableResult(ResultSet resultSet, String columnName) throws SQLException {
        return JsonUtils.fromString(resultSet.getString(columnName),UserInfo.class);
    }
    @Override
    public UserInfo getNullableResult(ResultSet resultSet, int columnIndex) throws SQLException {
        return JsonUtils.fromString(resultSet.getString(columnIndex),UserInfo.class);
    }
    @Override
    public UserInfo getNullableResult(CallableStatement callableStatement, int columnIndex) throws SQLException {
        return 
 JsonUtils.fromString(callableStatement.getString(columnIndex),UserInfo.class);
    }
}
其实还是将该对象转成了 json ,但是只不过转成 json 的工具类可以 由我们自己指定。
二、mybatisplus 存储枚举类型
        存储枚举类型有两种形式,第一种就是自定义  typeHandler 跟上面一样,还有一种是使用mybatis提供的默认的处理类,如下所所示:
数据库表结构:

          mybatisPlus对枚举处理器进行了补充:

         创建枚举类:
@Getter
public enum OrderState {
    NORMAL(0, "正常"),
    CANCEL(1, "取消"),
    DELETE(2, "删除");
 
    // 状态码
    @EnumValue // 用于数据库存储
    private Integer code;
    // 描述
    @JsonValue // 用于序列化返回的json数据
    private String desc;
 
    OrderState(Integer code, String desc) {
        this.code = code;
        this.desc = desc;
    }
 
}
         TOrder实体类:
@Data
@EqualsAndHashCode(callSuper = false)
@Accessors(chain = true)
@TableName("t_order")
public class TOrder implements Serializable {
 
    private static final long serialVersionUID = 1L;
 
    @TableId(value = "order_id", type = IdType.AUTO)
    private Integer orderId;
 
    @TableField("user_id")
    private Integer userId;
 
    @TableField("price")
    private BigDecimal price;
 
    @TableField("status")
    private OrderState status;
 
}
 在配置文件中配置统一的枚举处理器,实现类型转换:

        调用:
三、使用CommandLineRunner 修改 JacksonTypeHandler 实现类
@Component
public class JsonTypeHandlerConfig implements CommandLineRunner {
    @Override
    public void run(String... args) throws Exception {
        JacksonTypeHandler.setObjectMapper(JsonUtils.getMapper());
    }
}



![[图解]分析工作流开始01](https://i-blog.csdnimg.cn/direct/721279150fd94d13954187cb57359483.png)








![[Other]-安装ruby、ascli、ascp](https://i-blog.csdnimg.cn/direct/8bde72671aea47c49b2a5f52211900de.jpeg#pic_center)






