发布于 5年前

如何在Hibernate和MySQL中使用UUID

对于分布式数据库,自动增量ID不能正常工作。相反,我们应该使用UUID。让我们考虑一下UUID的优点和缺点,以及在Hibernate和MySQL中如何使用。 mysql

UUID简介

优点

通用唯一标识符(UUID)在每个数据库中都是全球唯一的!

这带来了以下优点:

  • 轻松合并来自不同数据库的条目。没有冲突的主键。

  • 轻松复制和同步分布式数据库。

  • 我们可以在任何地方生成UUID。因此,不需要往返数据库,因为我们可以在应用程序层中生成UUID。这也简化了测试,并允许轻松- 批量插入彼此引用的实体。

  • 可以猜测自动增量ID,这可能导致安全问题(例如,在URL中使用ID参数并刮掉所有内容)。

  • uuid

缺点

但是,也存在一些缺点:

  • UUID增加了值和索引所需的大小。单个UUID需要16个字节。相反,普通的int键只需要4个字节。
  • 他们使临时查询更加笨拙(见下文)。
  • REST资源中的UUID会增加有效负载大小。

创建一个表

UUID使用VARCHAR(36)数据类型并不是一个好主意。相反,我们应该使用 BINARY(16)。这最小化了所需的值大小和索引大小。但是,这会使查询更复杂一些。

CREATE TABLE product (
   `id` BINARY(16) NOT NULL primary key
   ,`name` varchar(64)
) ENGINE=InnoDB DEFAULT CHARSET=utf8;

Hibernate集成

Hibernate支持 java.util.UUID 和UUID生成。因此,Hibernate本身在客户端生成UUID。只需将以下注释添加到您的实体类:

@Id
@GeneratedValue(generator = "uuid2")
@GenericGenerator(name = "uuid2", strategy = "uuid2")
@Column(columnDefinition = "BINARY(16)")
private UUID id;

有用的SQL代码片段

我们可以使用uuid()生成的UUID。

SELECT uuid(); /*dbe07414-49d1-11e6-b7a7-0242ac140002*/

插入

请注意,uuid()返回带有破折号的UUID。我们必须使用replace()删除它们才能插入。此外,我们必须使用unhex()将十六进制(人类可读)UUID转换为其二进制表示。现在它适合BINARY(16)。

INSERT INTO product VALUES(
   unhex(replace(uuid(), '-', ''))
   , "car"
);

读取

使用hex()的UUID字节转换回其十六进制表示。

SELECT id, name FROM product;
/* BLOB, 'car' */
SELECT hex(id), name FROM product;
/* 'BFF641BA9F3A4584A1BA53824E7AB3B9', 'car' */

让我们使用查询某个UUID unhex()。

SELECT hex(id), name FROM product
   WHERE id = unhex('BFF641BA9F3A4584A1BA53824E7AB3B9');

/* or if you have a UUID with dashes: */
SELECT hex(id), name FROM product
   WHERE id = unhex(replace("2b08e375-275d-473e-910d-32700e34b61a", '-', ''));

Demo

在GitHub上,我创建了一个简单的Spring Boot + Hibernate/JPA 项目来演示UUID的实际运行情况。

译文地址 https://phauer.com/2016/uuids-hibernate-mysql/

©2020 edoou.com   京ICP备16001874号-3