有 Java 编程相关的问题?

你可以在下面搜索框中键入要查询的问题!

java如何使用复合类型的数组调用postgres函数

我正在寻找关于如何调用具有复合类型数组参数的postgres函数的建议。有人问过类似的问题,但我找到了令人满意的答案

我有以下复合类型:

CREATE TYPE collect.event_record AS (
    event_type      integer
  , event_timestamp timestamp without time zone
  , event_data      text
  , event_import_id integer
  );

我有以下功能:

CREATE OR REPLACE FUNCTION collect.insert_events(
    fail_on_duplicates boolean,
    source_public_id text,
    event_records collect.event_record[])
  RETURNS integer AS
  ...

在博士后方面,一切似乎都很顺利。现在我只需要从java/kotlin调用它

我们使用此版本的postgres驱动程序:

compile group: "org.postgresql", name: "postgresql", version: "9.4.1212"

PreparedStatement上,有一种方法似乎就是我想要的:

void setArray (int parameterIndex, Array x) throws SQLException;

数组类型为java.sql.Array,根据我所知,可以使用连接对象创建该类型:

Array createArrayOf(String typeName, Object[] elements) throws SQLException;

然而,在这里我不知道该放什么。应该是什么?我设想我应该创建一个与复合类型匹配的类,并根据需要序列化字段,或者它是一个java.sql.Struct数组

我一直在谷歌上搜索示例,但它们似乎主要处理基本类型,这对我的情况没有帮助

另一种方法是重构insert_events以接受多个基元类型的数组,类似于我的对象的列视图

另一种选择是发送一个JSON数组,我将其转换为postgres函数内的collect.event_record[]数组

然而,我想找到一种方法,使我能够保留我目前拥有的postgres函数签名

非常感谢您的任何想法


共 (1) 个答案

  1. # 1 楼答案

    据我所知,Postgres jdbc驱动程序不支持Struct,但对于复合类型的数组还有另一种解决方法。文档says表明可以使用以下构造创建复合类型的实例:(value_of_event_type,value_of_event_timestamp,value_of_event_data,value_event_import_id)event_record数据结构可以通过以下方式定义:

    data class EventRecord(
        val eventType: Int,
        val eventTimestamp: Instant,
        val eventData: String,
        val eventImportId: Int) {
    
        fun toSqlRow(): String {
            return ("(" + eventType + ","
                        + eventTimestamp + ","
                        + eventData + ","
                        + eventImportId +
                    ")")
        }
    }
    

    下一步是创建PreparedStatement

    val preparedStatement = con.prepareStatement("SELECT * FROM public.insert_events(?, ?, ?)")
    // ... define other parameters
    preparedStatement.setArray(3, con.createArrayOf("public.event_record", records.map { e -> e.toSqlRow() }.toTypedArray()))
    

    创建的PreparedStatement可用于查询数据库

    PS:当前实现对于包含,"'的文本值不起作用。如果文本值包含,,则将其用引号括起来,并将"替换为\"