zoukankan      html  css  js  c++  java
  • MyBatis里json型字段到Java类的映射(转)

    转自https://www.cnblogs.com/waterystone/p/5547254.html

    一、简介

      我们在用MyBatis里,很多时间有这样一个需求:POJO里有个属性是非基本数据类型,在DB存储时我们想存的是json格式的字符串,从DB拿出来时想直接映射成目标类型,也即json格式的字符串字段与Java类的相互类型转换

      当然,你可以为每个类写一个MyClassTypeHandler,但问题是要为每个类都写一个TypeHandler,过于繁琐。

      有了泛型,一个通用的TypeHandler直接搞定。

    二、源码

    详见:spring-mybatis-test

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
    29
    30
    31
    32
    33
    34
    35
    36
    37
    38
    39
    40
    41
    42
    43
    44
    45
    46
    47
    48
    49
    50
    51
    52
    53
    54
    55
    56
    57
    58
    59
    60
    61
    62
    63
    64
    65
    66
    67
    68
    69
    70
    71
    72
    73
    74
    75
    76
    77
    78
    79
    80
    81
    82
    83
    84
    85
    86
    87
    88
    package com.adu.spring_test.mybatis.typehandler;
     
    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;
    import org.codehaus.jackson.map.ObjectMapper;
    import org.codehaus.jackson.map.SerializationConfig.Feature;
    import org.codehaus.jackson.map.annotate.JsonSerialize.Inclusion;
     
     
    /**
     * mapper里json型字段到类的映射。
     * 用法一:
     * 入库:#{jsonDataField, typeHandler=com.adu.spring_test.mybatis.typehandler.JsonTypeHandler}
     * 出库:
     * <resultMap>
     * <result property="jsonDataField" column="json_data_field" javaType="com.xxx.MyClass" typeHandler="com.adu.spring_test.mybatis.typehandler.JsonTypeHandler"/>
     * </resultMap>
     *
     * 用法二:
     * 1)在mybatis-config.xml中指定handler:
     *      <typeHandlers>
     *              <typeHandler handler="com.adu.spring_test.mybatis.typehandler.JsonTypeHandler" javaType="com.xxx.MyClass"/>
     *      </typeHandlers>
     * 2)在MyClassMapper.xml里直接select/update/insert。
     *
     *
     * @author yunjie.du
     * @date 2016/5/31 19:33
     */
    public class JsonTypeHandler<T extends Object> extends BaseTypeHandler<T> {
        private static final ObjectMapper mapper = new ObjectMapper();
        private Class<T> clazz;
     
        public JsonTypeHandler(Class<T> clazz) {
            if (clazz == nullthrow new IllegalArgumentException("Type argument cannot be null");
            this.clazz = clazz;
        }
     
        @Override
        public void setNonNullParameter(PreparedStatement ps, int i, T parameter, JdbcType jdbcType) throws SQLException {
            ps.setString(i, this.toJson(parameter));
        }
     
        @Override
        public T getNullableResult(ResultSet rs, String columnName) throws SQLException {
            return this.toObject(rs.getString(columnName), clazz);
        }
     
        @Override
        public T getNullableResult(ResultSet rs, int columnIndex) throws SQLException {
            return this.toObject(rs.getString(columnIndex), clazz);
        }
     
        @Override
        public T getNullableResult(CallableStatement cs, int columnIndex) throws SQLException {
            return this.toObject(cs.getString(columnIndex), clazz);
        }
     
        private String toJson(T object) {
            try {
                return mapper.writeValueAsString(object);
            catch (Exception e) {
                throw new RuntimeException(e);
            }
        }
     
        private T toObject(String content, Class<?> clazz) {
            if (content != null && !content.isEmpty()) {
                try {
                    return (T) mapper.readValue(content, clazz);
                catch (Exception e) {
                    throw new RuntimeException(e);
                }
            else {
                return null;
            }
        }
     
        static {
            mapper.configure(Feature.WRITE_NULL_MAP_VALUES, false);
            mapper.setSerializationInclusion(Inclusion.NON_NULL);
        }
    }

      

    三、QA

    3.1 Q:Cause: java.lang.RuntimeException: Unable to find a usable constructor for class

    A:mybatis版本过低,类型不能识别,造成通用typeHandler的构造函数构造失败。之前用3.1.1时报过这个错,后来改成3.2.3就没问题了,现在用3.4.0也没问题。贴上现在的配置吧:

    复制代码
    <!-- mybatis -->
    <dependency>
        <groupId>org.mybatis</groupId>
        <artifactId>mybatis</artifactId>
        <version>3.4.0</version>
    </dependency>
    <dependency>
        <groupId>org.mybatis</groupId>
        <artifactId>mybatis-spring</artifactId>
        <version>1.3.0</version>
    </dependency>
  • 相关阅读:
    1、SpringBoot入门
    在一台电脑开启多个微信
    【监控】prometheus监控安装
    【hadoop3.0】hive 安装
    【google工具安装】gsutil存储管理google cloud stroge
    [监控报警]elastalert安装使用
    【大数据】hadoop3.0worker集群+flink+zeppelin+kafaka+zookeeper安装部署
    【原创】fluent-bit安装使用
    [etcd]etcd集群部署
    【手打】kafka集群设置
  • 原文地址:https://www.cnblogs.com/ffaiss/p/11430144.html
Copyright © 2011-2022 走看看