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 ==  null throw  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>

转载于:https://www.cnblogs.com/ffaiss/p/11430144.html

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值