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

13 篇文章 0 订阅

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

 

我就琢磨啊……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?!)

参考了很多资料,目前发现的主要可能成功的解决方法有三种

  1. 使用String类型代替(用特定符号做间隔);
  2. 在代码中添加一个继承了BaseTypeHandler的类;
  3. 在数据库添加一个自定义函数;

原先的项目里就是用的第一种(总觉得别别扭扭= =)

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

  • 4
    点赞
  • 12
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 5
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 5
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

AQin1012

求小鱼干呢~~

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值