Warning: file_get_contents(/data/phpspider/zhask/data//catemap/9/java/381.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
将PostgreSQL bytea存储的序列化java UUID转换为PostgreSQL UUID_Java_Postgresql_Serialization_Uuid_Bytea - Fatal编程技术网

将PostgreSQL bytea存储的序列化java UUID转换为PostgreSQL UUID

将PostgreSQL bytea存储的序列化java UUID转换为PostgreSQL UUID,java,postgresql,serialization,uuid,bytea,Java,Postgresql,Serialization,Uuid,Bytea,我们的一个软件项目使用一个PostgreSQL表,其列“guid”类型为bytea 这与hibernate 3.3.2.GA和PostgreSQL 8.4一起使用,后者使用。结果是一个类似以下escapeformat bytea literal的值: '\254\355\000\005sr\000\016java.util.UUID\274\231\003\367\230m\205/\002\000\002‌​J\000\014leastSigBitsJ\000\013mostSigBitsxp

我们的一个软件项目使用一个PostgreSQL表,其列“guid”类型为bytea

这与hibernate 3.3.2.GA和PostgreSQL 8.4一起使用,后者使用。结果是一个类似以下
escape
format bytea literal的值:

'\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 '
'\x0FCC6350118D11E4A5597DE5338EB025'
。。。我们不能在查询中轻松地使用它作为选择或条件来检索相关行


是否有人可以在不设置hibernate查询的情况下读取或使用查询的select或where部分(例如通过psql或pgadmin3)中的bytea列?

更新:请参见编辑到问题,此答案适用于常见的16字节uuid序列化;修改该问题是为了反映java序列化


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

因为
uuid
是一个固定大小的类型,
bytea
varlena
你不能只
创建cast。。。作为隐式的
对它们进行二进制强制,因为可变长度字段头会妨碍它们

bytea输入没有用于返回uuid的内置函数。这是一件方便的东西,但我认为还没有人做过

最简单的方法 更新:实际上有一种简单的方法可以做到这一点<一旦去掉
\x
,十六进制形式的code>bytea实际上是一个有效的uuid文本,因为
中的
uuid\u接受没有
-
{}
的普通未修饰十六进制。所以只要:

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文本:

'\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 '
'\x0FCC6350118D11E4A5597DE5338EB025'
您可以使用以下命令将其转换为
uuid
类型:

PL/Perl PL/Python 在Python中,它可能更快更干净,因为PL/Python接口将
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扩展模块


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

经过一些尝试和错误后,我创建了以下函数来提取PostgreSQL UUID值:

CREATE或REPLACE FUNCTION bytea2uuid(x bytea)将uuid返回为$$SELECT encode(子字符串(x,73,8)| |子字符串(x,65,8),'hex')::uuid$$language sql

这是通过提取leastSigBits和mostSigBits的java长值中使用的字节(以相反的顺序存储)来实现的,而不是编码为十六进制并强制转换为“uuid”类型

用法如下:
从文档限制1中选择bytea2uuid(guid)作为guid

“75bcc810-e204-4d20-bb92-29f02a72d2b2”
这对我来说很有用:

ALTER TABLE myTable ALTER COLUMN id TYPE uuid USING CAST(ENCODE(id, 'hex') AS uuid);

也许我应该更清楚地提到bytea列的内容是UUID实例的java序列化版本,例如:
selectguidfromdocumentslimit1
“\254\355\000\005sr\000\016java.util.UUID\274\231\003\367\230m\205/\002\000\002J\000\014leastSigBitsJ\000\013mostSigBitsxp\273\222)\360*r\322\262u\274\310\020\342\004M”
@FvHovell,是的。至少可以说,这是有用的。这就是为什么您应该始终包含示例数据。您最好也验证serialVersionUid字段,确保您没有解码错误。在一般情况下,您是正确的,但出于我的目的,我确信所有UUID序列化都是使用java 6执行的,因为java 6用于我们的所有项目。因此,在我的例子中,我不需要检查serialVersionUid,因为这保证对所有guid值都是相同的。这不是正确的编码:一个java.util.UUID序列化值,例如:“\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“