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

有目标就不怕路远。年轻人.无论你现在身在何方.重要的是你将要向何处去。只有明确的目标才能助你成功。没有目标的航船.任何方向的风对他来说都是逆风。因此,再遥远的旅程,只要有目标.就不怕路远。没有目标,哪来的劲头?一车尔尼雷夫斯基

导读:本篇文章讲解 解决Java连接PostgreSQL中数组类型(Array)的传参问题,希望对大家有帮助,欢迎收藏,转发!站点地址:www.bmabk.com,来源:原文

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

 

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

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

那么就试下”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>

效果

数据库插入效果

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

前端获取效果

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

成功~~撒花。*★,°*:.☆( ̄▽ ̄)/$:*.°★* 。

>>> 第三种方法由于未做尝试,效果未知,感兴趣的小伙伴可以参考Mybatis调用PostgreSQL存储过程实现数组入参传递_小灯光环-CSDN博客这篇博客自行尝试,本文也是参考了这篇博文,非常感谢~ 

版权声明:本文内容由互联网用户自发贡献,该文观点仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 举报,一经查实,本站将立刻删除。

文章由极客之音整理,本文链接:https://www.bmabk.com/index.php/post/135469.html

(0)
飞熊的头像飞熊bm

相关推荐

发表回复

登录后才能评论
极客之音——专业性很强的中文编程技术网站,欢迎收藏到浏览器,订阅我们!