上回书说到,我们把数据库存储数组的字符串转为了原生数组 bigint[]
类型,SQL
写起来是方便了,在 Java 代码里查询插入都会报错,要怎么使用呢?这里使用的是 MyBatis,所以就要扩展 MyBatis 的
typeHandler 了,具体内容如下,原理我也不清楚,因为都是
Copilot 帮我写的😁
代码
ExampleTypeHandler.java1 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
| public class ExampleTypeHandler extends BaseTypeHandler<List<Object>> {
@Override public void setNonNullParameter(PreparedStatement ps, int i, List<Object> parameter, JdbcType jdbcType) throws SQLException { if (parameter.size() == 0) { Connection conn = ps.getConnection(); Array array = conn.createArrayOf(JDBCType.BIGINT.getName(), new Long[0]); ps.setArray(i, array); array.free(); return; }
String typeName = null; if (parameter.get(0) instanceof Integer) { typeName = JDBCType.INTEGER.getName(); } else if (parameter.get(0) instanceof String) { typeName = JDBCType.VARCHAR.getName(); } else if (parameter.get(0) instanceof Boolean) { typeName = JDBCType.BOOLEAN.getName(); } else if (parameter.get(0) instanceof Double) { typeName = JDBCType.DOUBLE.getName(); } else if (parameter.get(0) instanceof Float) { typeName = JDBCType.FLOAT.getName(); } else if (parameter.get(0) instanceof Long) { typeName = JDBCType.BIGINT.getName(); } else if (parameter.get(0) instanceof Short) { typeName = JDBCType.SMALLINT.getName(); } else if (parameter.get(0) instanceof Byte) { typeName = JDBCType.TINYINT.getName(); } if (typeName == null) { throw new TypeException("ArrayTypeHandler parameter typeName error, your type is " + parameter.getClass().getName()); }
Connection conn = ps.getConnection(); Array array = conn.createArrayOf(typeName, parameter.toArray()); ps.setArray(i, array); array.free(); }
@Override public List<Object> getNullableResult(ResultSet resultSet, String s) throws SQLException { return getList(resultSet.getArray(s)); }
@Override public List<Object> getNullableResult(ResultSet resultSet, int i) throws SQLException { return getList(resultSet.getArray(i)); }
@Override public List<Object> getNullableResult(CallableStatement callableStatement, int i) throws SQLException { return getList(callableStatement.getArray(i)); }
private List<Object> getList(Array array) { if (array == null) { return Collections.emptyList(); } try { Object[] objects = (Object[]) array.getArray(); array.free(); return Arrays.stream(objects).collect(Collectors.toList()); } catch (Exception ignored) { } return null; } }
|
配置
完成了自定义的 typeHandler 后,只需要在 MyBatis 中配置好 typeHandler 就可以正确处理数组类型的数据了。
文档中是使用的 xml 配置文件来配置的。
mybatis-config.xml1 2 3 4
| <typeHandlers> <typeHandler handler="org.mybatis.example.ExampleTypeHandler"/> </typeHandlers>
|
这里使用的是注解的方式来配置,首先是 POJO 属性上指定 @ColumnType(typeHandler = ExampleTypeHandler.class)
ExamplePO.java1 2
| @ColumnType(typeHandler = ExampleTypeHandler.class) private List<Long> longList;
|
然后在 mapper.xml 文件中设置 typeHandler
ExampleMapper.xml1 2 3 4 5 6 7 8 9 10 11
| <resultMap id="BaseResultMap" type="org.mybatis.example.ExamplePO"> ... <result column="bigint_array" jdbcType="ARRAY" property="longList" typeHandler="org.mybatis.example.ExampleTypeHandler"/> ... </resultMap>
<select id="list" resultMap="BaseResultMap"> ... bigint_array <![CDATA[&&]]> #{queryList, jdbcType=ARRAY, typeHandler=org.mybatis.example.ExampleTypeHandler} ... </select>
|