Transfer from https://www.cnblogs.com/waterystone/p/5547254.html
I. Introduction
We use MyBatis, many times there is such a demand: POJO there attributes non-basic data types, stored in the DB when we want to keep the string json format directly mapped to the destination type from the DB out, i.e. json type string fields each Java class format conversion .
Of course, you can write a MyClassTypeHandler for each class, but the problem is to write a TypeHandler for each class, too cumbersome.
With generics, a generic TypeHandler get directly.
Second, the source
See: the Spring-the mybatis-the 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>