java - 从 Java 中的 Postgres 加载非物化数组
问题描述
设置:
我正在使用 Java 连接到 Postgres 数据库,并尝试加载pg_stats.histogram_bounds
统计信息,该统计信息是 Postgres 中的一个数组。我可以将字段提取为sql.Array
对象Array histogramBounds = rs.getArray("histogram_bounds");
。这个对象可以用 打印toString()
,但我不能以其他方式访问任何数据(例如对histogramBounds.getArray()
、的调用getBaseType
等)都生成PSQLException: No results were returned by the query.
。
文档以及各种教程和 SE 问题表明这应该是有效的。
显然sql.Array
对象不直接保存数组数据,而是在服务器上指向它。从我的实验中,我得到了以下 MWE,它显示了存储在 Postgres 中的表中的数组值与某种短暂或非物化的数组值之间的差异(我怀疑pg_stats
可能是其他内部表的视图)。
MWE:
我有两个查询,一个从表中选择数据并工作,另一个直接从查询中选择数据,但不工作。我在文档中看不到任何原因,它们不应该同时工作,我想让第二个版本工作以获取 Java 数组[1, 2, 3]
。令人困惑的是,toString
在第二种情况下仍然正确显示数据,因此它必须在某个时候成功加载。
import java.sql.Array;
import java.sql.Connection;
import java.sql.DriverManager;
import java.sql.ResultSet;
import java.sql.SQLException;
import java.sql.Statement;
public class PostgresStatsExperiments {
public static void main(String[] args) throws SQLException {
Connection conn = DriverManager.getConnection("jdbc:postgresql://localhost/tmp", "admin", "admin");
Statement stmt = conn.createStatement();
ResultSet rs = stmt.executeQuery("SELECT name, my_data from array_test;"); // This one works
//ResultSet rs = stmt.executeQuery("SELECT '{1, 2, 3}' AS my_data;"); // This one does not work.
while (rs.next()) {
Array myData = rs.getArray("my_data");
System.out.println(myData);
System.out.println(myData.getArray()); // PSQLException here in the second case
}
stmt.close();
rs.close();
conn.close();
}
}
该表array_test
如下所示:
create table array_test ( name varchar, my_data integer ARRAY[3] );
insert into array_test values ('Alice', '{1, 2, 3}');
insert into array_test values ('Bob', '{4, 5, 6}');
在第二种情况下,我得到以下输出:
{1, 2, 3}
Exception in thread "main" org.postgresql.util.PSQLException: No results were returned by the query.
at org.postgresql.jdbc2.TypeInfoCache.getPGArrayElement(TypeInfoCache.java:425)
at org.postgresql.jdbc2.AbstractJdbc2Array.buildArray(AbstractJdbc2Array.java:540)
at org.postgresql.jdbc2.AbstractJdbc2Array.getArrayImpl(AbstractJdbc2Array.java:171)
at org.postgresql.jdbc2.AbstractJdbc2Array.getArray(AbstractJdbc2Array.java:128)
at tmp.PostgresStatsExperiments.main(PostgresStatsExperiments.java:21)
我使用postgresql-9.3-1102-jdbc41.jar
的是 Maven,最新的42.2.4.jre7
.
解决方案
在查询SELECT '{1, 2, 3}' AS my_data
中,该列my_data
不是任何数组。这是一个恰好看起来像数组的字符串 - 但单引号表示一个text
(或varchar
)值。
并且由于列的数据类型不是数组,调用getArray()
会抛出异常。
如果需要数组,则需要将文本值转换为数组:
SELECT '{1, 2, 3}'::int[] AS my_data;
或更好:使用显式数组构造函数:
SELECT array[1, 2, 3] AS my_data;
pg_stats.histogram_bounds
被定义为anyarray
- 它不是一个类型化数组,因为它包含每列的不同数据类型(这意味着在每一行中,因为该表每个表列包含一行)。
显然 JDBC 驱动程序无法正常anyarray
工作。
为了处理 Java 代码中的值,我认为最简单的方法是将其转换为字符串,然后可以将其转换回文本数组(因为字符串表示是正确的)。
因此,如果您使用以下查询:
select schemaname, tablename, attname, histogram_bounds::text::text[] as histogram_bounds, ..
from pg_stats
where ...
您应该能够检索histogram_bounds
列的内容(但是您将所有内容都作为字符串,而不是与列的数据类型匹配的数据类型)。
推荐阅读
- corda - 存储 UniqueIdentifier 作为对其他状态的引用
- java - 接口声明为 NULL
- android - 将cardview添加到相对布局,将相对布局添加到scrollview
- apache-spark - Spark 和远程 HDFS 之间的通信
- android - 使用 TableLayout 膨胀问题
- c# - .NET SerialPort 在连接到套接字时被阻止
- android - Firebase 动态链接仅在 Facebook 上被视为垃圾邮件且 Facebook 未显示元数据预览
- apache-camel - Apache骆驼路由、activemq和mybatis——传参
- jsf - 捕获 ap:dataTable 的单个单元格
- vuetify.js - Vuetify:如何在同一行对齐图标和长文本?