irpas技术客

解决Java连接PostgreSQL中数组类型(Array)的传参问题_AQin1012

未知 4644

想传个数组咋就那么难...(只看解决方法可以果断跳第二部分)

?

我就琢磨啊……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博客这篇博客自行尝试,本文也是参考了这篇博文,非常感谢~?


1.本站遵循行业规范,任何转载的稿件都会明确标注作者和来源;2.本站的原创文章,会注明原创字样,如未注明都非原创,如有侵权请联系删除!;3.作者投稿可能会经我们编辑修改或补充;4.本站不提供任何储存功能只提供收集或者投稿人的网盘链接。

标签: #TypeHandler #found #for #property