自定义typeHandler的使用

简单TypeHandler 的使用

mybatis是一个常用的一个ORM框架,但是mybatis提供的TypeHandler往往是不够用的,例如某些数据库支持json、数组等的支持,但是mybatis对于这些数据类型没有支持,接下来就需要我们自定义TypeHandler了。

1、创建TypeHandler类继承BaseTypeHandler。

下面是一个针对数组类型的TypeHandler,并实现方法

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
89
90
91
92
public class ArrayTypeHandler extends BaseTypeHandler<Object[]> {
private static final String TYPE_NAME_VARCHAR = "varchar";
private static final String TYPE_NAME_INTEGER = "integer";
private static final String TYPE_NAME_BOOLEAN = "boolean";
private static final String TYPE_NAME_NUMERIC = "numeric";

private Logger logger = LoggerFactory.getLogger(this.getClass());

/**
* 设置非空参数
*
* @param ps PreparedStatement
* @param parameterIndex 参数i
* @param parameter 参数数组
* @param jdbcType jdbcType
* @throws SQLException
*/
@Override
public void setNonNullParameter(PreparedStatement ps, int parameterIndex, Object[] parameter, JdbcType jdbcType) throws SQLException {
String typeName = null;
if (parameter instanceof Integer[]) {
typeName = TYPE_NAME_INTEGER;
} else if (parameter instanceof String[]) {
typeName = TYPE_NAME_VARCHAR;
} else if (parameter instanceof Boolean[]) {
typeName = TYPE_NAME_BOOLEAN;
} else if (parameter instanceof Double[]) {
typeName = TYPE_NAME_NUMERIC;
}

if (typeName == null) {
throw new TypeException("ArrayTypeHandler parameter typeName error, your type is " + parameter.getClass().getName());
}

// 这3行是关键的代码,创建Array,然后ps.setArray(parameterIndex, array)就可以了
Connection conn = ps.getConnection();
Array array = conn.createArrayOf(typeName, parameter);
ps.setArray(parameterIndex, array);

}

/**
* 获取可以为null的结果集
*
* @param resultSet 结果集
* @param columnName 列名
*/
@Override
public Object[] getNullableResult(ResultSet resultSet, String columnName) throws SQLException {
return getArray(resultSet.getArray(columnName));
}


/**
* 获取可以为null的结果集
*
* @param resultSet 结果集
* @param columnIndex columnIndex 列标
*/
@Override
public Object[] getNullableResult(ResultSet resultSet, int columnIndex) throws SQLException {
return getArray(resultSet.getArray(columnIndex));
}

/**
* 获取可以为null的结果集
*
* @param callableStatement CallableStatement
* @param paramIndex 列号
*/
@Override
public Object[] getNullableResult(CallableStatement callableStatement, int paramIndex) throws SQLException {
return getArray(callableStatement.getArray(paramIndex));
}

/**
* 将ARRAY 转为 java数组
*
* @param array 数组
* @return
*/
private Object[] getArray(Array array) {
if (array == null) {
return null;
}
try {
return (Object[]) array.getArray();
} catch (Exception e) {
logger.error("ARRAY转为java数组出错", e);
}
return null;
}

2、接下来在项目中使用TypeHandler使用

1)最简单粗暴的方式为在xml文件中直接指定TypeHandler

1
username_arr=#{username_arr,typeHandler=xxx.xxx.ArrayTypeHandler}::VARCHAR[]

2)在项目中引入TypeHandler

在mybatis的配置文件中添加typeHandler标签 如下所示

1
2
3
<typeHandlers>
<typeHandler handler="org.mybatis.example.ExampleTypeHandler"/>
</typeHandlers>

然后在自定义Typehandler上添加@MappedTypes和@MappedJdbcTypes注解。例如对于数组类型的TypeHandler,如下所示

1
2
@MappedTypes({Integer[].class,String[].class,Boolean[].class,Number[].class})
@MappedJdbcTypes(value = {JdbcType.ARRAY},includeNullJdbcType = true)

然后在对应字段上就可以自动使用typeHandler了,例如用户名数组为位String数组,对应到数据库上就是varchar[],就可以如下使用

1
username_arr=#{username_arr}::VARCHAR[]