如何使用 Phoenix JDBC 编写 Binary 类型的数组(序列化对象)?

问题描述 投票:0回答:1

我正在尝试使用 Phoenix 查询服务器 创建一个瘦phoenix JDBC 客户端,该客户端可以读取数据并将数据写入底层Phoenix/Hbase 数据库。

我正在努力弄清楚如何编写 BINARY 类型数组的列。这些 BINARY 元素是自定义 Bean 的序列化形式。

定义列的架构中的相关代码:

mySerializedArrayCol BINARY(800)[],

我正在使用 java.sql.PrepareStatement 来构建查询。这是迄今为止我最失败的尝试:

        String SQL = "UPSERT INTO myTable VALUES(?,?,?,?,?,?,?)";

        Connection connection = getNewConnection();
        PreparedStatement pstmt = connection.prepareStatement(SQL);

        //...
        
        pstmt.setArray(5, connection.createArrayOf("BINARY",
                Arrays.stream(myObjectArray)
                        .map(obj -> SerializationUtils.serialize(obj))
                        .toArray(byte[][]::new)
        ));


        pstmt.executeUpdate();
        connection.commit();

运行时会在运行时抛出 NullPointerException

executeUpdate()
:

java.lang.NullPointerException
    at org.apache.phoenix.schema.types.PArrayDataType.toBytes(PArrayDataType.java:142)
    at org.apache.phoenix.expression.LiteralExpression.newConstant(LiteralExpression.java:193)
    at org.apache.phoenix.expression.LiteralExpression.newConstant(LiteralExpression.java:174)
    at org.apache.phoenix.expression.LiteralExpression.newConstant(LiteralExpression.java:161)
    at org.apache.phoenix.compile.UpsertCompiler$UpdateColumnCompiler.visit(UpsertCompiler.java:888)
    at org.apache.phoenix.compile.UpsertCompiler$UpdateColumnCompiler.visit(UpsertCompiler.java:872)
    at org.apache.phoenix.parse.BindParseNode.accept(BindParseNode.java:47)
    at org.apache.phoenix.compile.UpsertCompiler.compile(UpsertCompiler.java:761)
    at org.apache.phoenix.jdbc.PhoenixStatement$ExecutableUpsertStatement.compilePlan(PhoenixStatement.java:787)
    at org.apache.phoenix.jdbc.PhoenixStatement$ExecutableUpsertStatement.compilePlan(PhoenixStatement.java:773)
    at org.apache.phoenix.jdbc.PhoenixStatement$2.call(PhoenixStatement.java:403)
    at org.apache.phoenix.jdbc.PhoenixStatement$2.call(PhoenixStatement.java:393)
    at org.apache.phoenix.call.CallRunner.run(CallRunner.java:53)
    at org.apache.phoenix.jdbc.PhoenixStatement.executeMutation(PhoenixStatement.java:392)
    at org.apache.phoenix.jdbc.PhoenixStatement.executeMutation(PhoenixStatement.java:380)
    at org.apache.phoenix.jdbc.PhoenixPreparedStatement.execute(PhoenixPreparedStatement.java:173)
    at org.apache.phoenix.jdbc.PhoenixPreparedStatement.execute(PhoenixPreparedStatement.java:183)
    at org.apache.calcite.avatica.jdbc.JdbcMeta.execute(JdbcMeta.java:868)
    at org.apache.calcite.avatica.remote.LocalService.apply(LocalService.java:254)
    at org.apache.calcite.avatica.remote.Service$ExecuteRequest.accept(Service.java:1031)
    at org.apache.calcite.avatica.remote.Service$ExecuteRequest.accept(Service.java:1001)
    at org.apache.calcite.avatica.remote.AbstractHandler.apply(AbstractHandler.java:94)
    at org.apache.calcite.avatica.remote.ProtobufHandler.apply(ProtobufHandler.java:46)

将 phoenix 4.14.3 与 Hbase 1.4 和 Java8 结合使用。

因此,我实际上能够在单独的 Scala 程序中使用 phoenix-spark 连接器将数据帧正确写入同一个表中。 我还可以使用 phoenix JDBC 读取同一个表并正确反序列化对象数组。 我真的不确定为什么这特别失败,并且找不到任何有关如何处理二进制/序列化对象数组的文档。

serialization jdbc apache-phoenix
1个回答
0
投票

我对此进行了调试,发现错误来自 Phoenix 服务器端。客户端似乎正在按预期构造查询对象。

我最终通过将序列化数组包装在另一个对象中来更改我的数据模式,以便我可以只存储序列化包装对象而不是序列化对象数组..

因此,phoenix 模式中的行来自:

mySerializedArrayCol BINARY(800)[]

至:

mySerializedArrayCol VARBINARY

我认为从数据工程的角度来看,这是更标准的方法,考虑到我发现了 0 篇帖子,有人尝试上面的初始模式。但是,它需要在项目的其他组件中进行额外的工作,这些组件需要进行转换以处理新的包装数组模式。

Phoenix 确实声称支持 Binary 类型的数组,如果能得到一些闭包就太好了:shrug:

© www.soinside.com 2019 - 2024. All rights reserved.