java - 将 PostgreSQL bytea-stored serialized-java-UUID 转换为 postgresql-UUID

标签 java postgresql serialization uuid bytea

我们的一个软件项目使用了一个 PostgreSQL 表,其中包含 bytea 类型的“guid”列。

这与 hibernate 3.3.2.GA 和 PostgreSQL 8.4 一起使用,它使用 java object serialization 序列化 java UUID 类型.结果是类似于以下 escape 格式 bytea 文字的值:

'\254\355\000\005sr\000\016java.util.UUID\274\231\003\367\230m\205/\002\000\002‌​J\000\014leastSigBitsJ\000\013mostSigBitsxp\273\222)\360*r\322\262u\274\310\020\3‌​42\004M '

...我们不能轻易在查询中将其用作选择或条件来检索相关行。

有没有人有办法在查询的 select 或 where 部分读取或使用 bytea 列(例如通过 psql 或 pgadmin3),而无需设置一些 hibernate 查询?

最佳答案

更新:请参阅对问题的编辑,此答案适用于 uuid 的常见 16 字节序列化;修改了问题以反射(reflect) java 序列化


有趣的问题。我着手编写一个简单的 C 扩展来高效地完成它,但使用下面的 PL/Python 版本可能更明智。

因为 uuid 是一个固定大小的类型而 byteavarlena 你不能只是 create cast ... as implicit 对它们进行二进制强制转换,因为可变长度字段 header 会妨碍。

bytea 输入没有返回 uuid 的内置函数。拥有它会很方便,但我认为还没有人这样做过。

最简单的方法

更新:实际上有一种简单的方法可以做到这一点。一旦 \x 被剥离,十六进制形式的 bytea 实际上是一个有效的 uuid 文字,因为 uuid_in 接受没有 的普通未修饰的十六进制 - {}。所以只是:

regress=> SET bytea_output = 'hex';
SET
regress=> SELECT CAST( substring(CAST (BYTEA '\x0FCC6350118D11E4A5597DE5338EB025' AS text) from 3) AS uuid);
              substring               
--------------------------------------
 0fcc6350-118d-11e4-a559-7de5338eb025
(1 row)

它涉及几个字符串副本和一个十六进制编码/解码周期,但它比我之前建议的任何 PL 答案都快很多,尽管比 C 慢。

其他选项

我个人推荐使用 PL/Perl 或 pl/pythonu。我将跟进一个例子。

假设您的 uuid 是十六进制格式的 bytea 文字:

'\x0FCC6350118D11E4A5597DE5338EB025'

你可以把它变成一个 uuid 类型:

PL/Perl

create language plperlu;

create or replace function to_uuid(bytea) returns uuid language plperlu immutable as $$
use Data::UUID;
my $ug = new Data::UUID;
my $uuid = $ug->from_hexstring(substr($_[0],2));
return $ug->to_string($uuid);
$$
SET bytea_output = hex;

SELECT to_uuid(BYTEA '\x0FCC6350118D11E4A5597DE5338EB025');

PL/Python

它在 Python 中可能更快更干净,因为 PL/Python 接口(interface)将 bytea 作为原始字节而不是十六进制字符串传递:

CREATE LANGUAGE plpythonu;

CREATE or replace function to_uuid(uuidbytes bytea) 
RETURNS uuid LANGUAGE plpythonu IMMUTABLE 
AS $$
import uuid
return uuid.UUID(bytes=uuidbytes)
$$;

SELECT to_uuid(BYTEA '\x0FCC6350118D11E4A5597DE5338EB025');

在 C 中,只是为了好玩。丑陋的骇客。

可以看到C扩展模块here .

但说真的,我的意思是它很丑。如果你想在 C 中正确地完成它,最好实际修补 PostgreSQL 而不是使用扩展。

关于java - 将 PostgreSQL bytea-stored serialized-java-UUID 转换为 postgresql-UUID,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/24883127/

相关文章:

java - 单例延迟加载模式

java - 如何从 java 应用程序使用 OSGi

java - cordova.exec 错误 未找到类

php - 通过PHP保存用户输入

sql - PostGIS - 合并不同组中的缓冲区几何(相交时)

php - 检查字符串是否被序列化?

java - 根据客户端交付不同的 ssl 证书

postgresql - 如何安装 zombodb elasticsearch 插件?

python - 在将数据传递给序列化器 django api 时添加额外的上下文

Java - 如何将复杂对象(不可序列化)保存到文件中?