专栏名称: ImportNew
伯乐在线旗下账号,专注Java技术分享,包括Java基础技术、进阶技能、架构设计和Java技术领域动态等。
目录
相关文章推荐
芋道源码  ·  如何应对消息堆积? ·  19 小时前  
Java编程精选  ·  WebSocket 的 6 ... ·  昨天  
芋道源码  ·  Spring ... ·  昨天  
芋道源码  ·  为了DDD 熬夜撸了一套 IDEA 插件) ·  昨天  
51好读  ›  专栏  ›  ImportNew

Hibernate 和 UUID 标示符

ImportNew  · 公众号  · Java  · 2017-01-17 20:32

正文

(点击 上方公众号 ,可快速关注)


源:伯乐在线 - shijiwen,

如有好文章投稿,请点击 → 这里了解详情

如需转载,发送「转载」二字查看说明


简介


在前一篇博客 (https://www.javacodegeeks.com/2014/06/database-primary-key-flavors.html)中,我们讨论了UUID代理键(surrogate keys)以及比自增标示符更适用的使用场景。


UUID的数据库生成方式


有很多种方式可表达一个128位UUID。每当遇到疑问时,我喜欢用stack exchange来作为权威参考。


由于表ID一般会建索引,经过压缩的数据类型会占用更少的空间。按照效率由高到低有如下几种选择:


  1. 一部分数据库(PostgreSQL, SQL Server) 提供了专门的UUID 存储数据类型。


  2. 另外还可把若干bit存放到字节数组(比如Oracle 的RAW(16) 或标准类型的BINARY(16) )。


  3. 或可用2个bigint列(64位),但这种复合列的ID的效率低于单一列。


  4. 把16进制值存入一个char(36)列(其包含32个16进制数和4个”-“),但这会占用很多磁盘空间,所以只是一个低效备选方案。


Hibernate提供了多种id策略供选择,针对UUID有以下三种:


  • 由应用程序逻辑来分配的uuid生成。


  • 16进制的字符串uuid生成器。


  • uuid2生成器更灵活些。它可以借用 java.lang.UUID ,这是16个字节数据或16进制字符串。


(程序)自定义生成方式


自定义生成方式可以让应用程序的逻辑来处理实体ID的生成过程。Hibernate通过简单的忽略ID生成器定义来处理自定义ID。由于数据库使用了HSQLDB,所以下面示例使用BINARY(16) 列类型。


@Entity(name = "assignedIdentifier")

public static class AssignedIdentifier {

@Id

@Column(columnDefinition = "BINARY(16)")

private UUID uuid;

public AssignedIdentifier() {

}

public AssignedIdentifier(UUID uuid) {

this.uuid = uuid;

}

}


持久化实体:


session.persist(new AssignedIdentifier(UUID.randomUUID()));

session.flush();


具体生成一个INSERT语句:


Query:{[insert into assignedIdentifier (uuid) values (?)][[B@76b0f8c3]}


我们可以看看使用merge后会发生什么:


session.merge(new AssignedIdentifier(UUID.randomUUID()));

session.flush();


这次既有select查询又有insert:


Query:{[select assignedid0_.uuid as uuid1_0_0_ from assignedIdentifier assignedid0_ where assignedid0_.uuid=?][[B@23e9436c]}

Query:{[insert into assignedIdentifier (uuid) values (?)][[B@2b37d486]}


持久化方法会把transient实体添加到当前Hibernate session中。不过,如果session已有其他实体或当前实体已被去除,就会抛出一个exception。如果需要,针对transient实体和已去除的实体,合并操作会复制当前对象的状态到已持久化的实体中。但transient实体的持久化比合并要高效很多。


对于已生成的ID,由于Hibernate并不能知道库中有重复ID,所以合并还需要一次select查询。对于其他的ID生成器,Hibernate会找一空ID来判断该实体有没有处于transient状态。因此,如果使用自定义ID,那么Spring Data包里面 SimpleJpaRepository#save(S entity) 方法并不是最好选择:







请到「今天看啥」查看全文