想传个数组咋就那么难…(只看解决方法可以果断跳第二部分)
我就琢磨啊……Java连接PostgreSQL时相传个数组咋就那么难,各种报错,当时项目赶得急就用字符串代替了(中间用个分号逗号的分隔下),每次出库入库都要做转换,虽然也不是很麻烦吧,但就总觉得这么处理不是个事(抠鼻ing)
明明PostgreSQL是支持数组这个结构的
明明Java也是有数组这个结构的
那我还不信了。。。根据各种尝试中的一次报错
Caused by: org.apache.ibatis.builder.BuilderException: Error resolving JdbcType. Cause: java.lang.IllegalArgumentException: No enum constant org.apache.ibatis.type.JdbcType.INT[]
定位到了JdbcType这个枚举类上,从源码可以看出这个类跟数组有关的只有 “ARRAY(2003)”
那么就试下”ARRAY”
于是又报了”No typehandler found for property xxx”的错(/(ㄒoㄒ)/~~)
Caused by: java.lang.IllegalStateException: No typehandler found for property testArr
因为PostgreSQL中并没有可以对应的类型 (WHAT?!)
参考了很多资料,目前发现的主要可能成功的解决方法有三种
- 使用String类型代替(用特定符号做间隔);
- 在代码中添加一个继承了BaseTypeHandler的类;
- 在数据库添加一个自定义函数;
原先的项目里就是用的第一种(总觉得别别扭扭= =)
SO! 对Java熟悉程度高于PostgreSQL的我果断选择了尝试下第二种方法。。。嘿嘿
解决篇
直接上全部代码
package com.aqin.services;
import org.apache.ibatis.type.BaseTypeHandler;
import org.apache.ibatis.type.JdbcType;
import org.apache.ibatis.type.TypeException;
import java.sql.*;
/**
* @Description
* @Author AQin1012.
* @CreateTime 2021/9/22 19:12
* @Version
**/
public class ArrayTypeHandler extends BaseTypeHandler<Object[]> {
private static final String ARRAY_TYPE_INTEGER = "integer";
private static final String ARRAY_TYPE_VARCHAR = "varchar";
private static final String ARRAY_TYPE_NUMERIC = "numeric";
private static final String ARRAY_TYPE_BOOLEAN = "boolean";
//……
@Override
public void setNonNullParameter(PreparedStatement preparedStatement, int i, Object[] objects, JdbcType jdbcType) throws SQLException {
String typeName = null;
if (objects instanceof Integer[]) {
typeName = ARRAY_TYPE_INTEGER;
} else if (objects instanceof String[]) {
typeName = ARRAY_TYPE_VARCHAR;
} else if (objects instanceof Double[]) {
typeName = ARRAY_TYPE_NUMERIC;
}else if (objects instanceof Boolean[]) {
typeName = ARRAY_TYPE_BOOLEAN;
}
if (typeName == null) {
throw new TypeException(objects.getClass().getName()+" can not match a array-type");
}
Connection connection = preparedStatement.getConnection();
Array array = connection.createArrayOf(typeName, objects);
preparedStatement.setArray(i, array);
}
@Override
public Object[] getNullableResult(ResultSet resultSet, String s) throws SQLException {
return getArray(resultSet.getArray(s));
}
@Override
public Object[] getNullableResult(ResultSet resultSet, int i) throws SQLException {
return getArray(resultSet.getArray(i));
}
@Override
public Object[] getNullableResult(CallableStatement callableStatement, int i) throws SQLException {
return getArray(callableStatement.getArray(i));
}
private Object[] getArray(Array array) {
if (array == null) {
return null;
}
try {
return (Object[]) array.getArray();
} catch (Exception e) {
}
return null;
}
}
配置文件
映射配置时需要增加typeHandler属性(ArrayTypeHandler.java的全路径)
<resultMap>
<result column="test_arr" property="testArr" jdbcType="ARRAY" typeHandler="com.aqin.services.ArrayTypeHandler"/>
</resultMap>
xxxMapper.xml中用到的SQL写法
<insert id="insert" useGeneratedKeys="true" keyProperty="id"
parameterType="com.aqin.services.ProductionDO">
insert into production(created_time, modified_time,production_name, organization_name, phone_number, test_arr)
values (#{createdTime}, #{modifiedTime}, #{productionName}, #{organizationName}, #{phoneNumber},#{testArr,jdbcType=ARRAY,typeHandler=com.leadinsight.services.credit.utils.ArrayTypeHandler})
</insert>
效果
数据库插入效果
前端获取效果
成功~~撒花。*★,°*:.☆( ̄▽ ̄)/$:*.°★* 。
>>> 第三种方法由于未做尝试,效果未知,感兴趣的小伙伴可以参考Mybatis调用PostgreSQL存储过程实现数组入参传递_小灯光环-CSDN博客这篇博客自行尝试,本文也是参考了这篇博文,非常感谢~
版权声明:本文内容由互联网用户自发贡献,该文观点仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 举报,一经查实,本站将立刻删除。
文章由极客之音整理,本文链接:https://www.bmabk.com/index.php/post/135469.html