将 Java UUID 存储在二进制数据库列中,Hibernate/JPA 与原始 JDBC
Posted
技术标签:
【中文标题】将 Java UUID 存储在二进制数据库列中,Hibernate/JPA 与原始 JDBC【英文标题】:Storing Java UUID's in binary database columns, Hibernate/JPA vs. raw JDBC 【发布时间】:2016-11-03 06:32:19 【问题描述】:Hibernate/JPA 的 UUID
我一直习惯于将 UUID 值存储在二进制数据库列中(例如,BYTEA
用于 PostgreSQL,BINARY(16)
用于 mysql)。使用 Hibernate 和 JPA 时,我可以像这样注释我的实体字段...
@Id
@Column(name = "id", columnDefinition = "BINARY(16)")
private UUID id;
...它只是工作。
带有 JDBC 的 UUID
在我需要编写使用 JDBC 的情况下,我编写了这样的 UUID 值...
PreparedStatement ps = new PreparedStatement("INSERT INTO foo (id) VALUES (?)");
ps.setObject(1, uuid, Types.BINARY)
...并像这样读取 UUID 值...
while (rs.net()
UUID id = UUID.nameUUIDFromBytes(rs.getBytes("id"));
混搭?
最近我拿了一个 Hibernate/JPA 应用程序使用的 MySQL 数据库,用mysqldump
工具导出和导入它,并尝试使用一些原始 JDBC 代码使用数据。 Hibernate/JPA 代码和读写 UUID,原始 JDBC 代码可以读写 UUID。但是,如果我:
-
使用 JDBC 读取最初由 Hibernate/JPA 编写的 UUID,并且
让我的 JDBC 代码在别处写入相同的 UUID,然后
JDBC 代码存储在 MySQL 中的值与原始值不匹配!
有没有人以前见过这个,或者有任何理论?我不完全理解 Hibernate/JPA 如何在幕后序列化 UUID 值,所以我不确定我可能需要对原始 JDBC 代码做些什么来产生相同的结果。
谢谢!
【问题讨论】:
顺便说一句,Postgres 支持UUID as a data type,包括索引和主键。在 JDBC 驱动中使用getObject
/setObject
。
【参考方案1】:
答案在Mysql Documentation for Binary and Varbinary。
The BINARY and VARBINARY types are similar to CHAR and VARCHAR, except that they contain binary strings rather than nonbinary strings. That is, they contain byte strings rather than character strings. This means that they have no character set, and sorting and comparison are based on the numeric values of the bytes in the values.
mysql中的二进制存储二进制字符串,这意味着字节字符串不是字符。
如果您想按原样使用 UUID,最好在 mysql 和 postgresql 中都使用 VARCHAR 类型。
声明
@Id
@Column(name = "id")
private String id;
写入数据库
PreparedStatement ps = new PreparedStatement("INSERT INTO foo (id) VALUES (?)");
ps.setObject(1, uuid.toString());
从数据库中读取。
while (rs.net()
UUID id = UUID.fromString(rs.getString("id"));
【讨论】:
嗯... mysqldump 导出文件包含一个十六进制 UUID 值:X'581fc98ce7c447898de130d0b01759e5'
。但是,当我尝试按照您的建议从ResultSet
中将其作为字符串读取时,出现错误:java.lang.IllegalArgumentException: Invalid UUID string: 581fc98ce7c447898de130d0b01759e5
。
啊!问题只是 MySQL 存储了一个 没有连字符 的 UUID 字符串,而 Java 的 UUID.fromString()
方法无法处理缺少连字符的问题。我将它与另一个 *** 问题中讨论的正则表达式结合使用:***.com/questions/18986712/…
感谢您提供快速而详细的帮助!以上是关于将 Java UUID 存储在二进制数据库列中,Hibernate/JPA 与原始 JDBC的主要内容,如果未能解决你的问题,请参考以下文章
如何从 MySQL/MariaDB 中的二进制列格式化 uuid 字符串
使用 Laravel 关系 orm 时 UUID 二进制(16)的问题