介绍

在我以前的文章中,我谈到了不同的数据库标识符策略。 这篇文章将比较最常见的替代主要关键策略:

  • 身份
  • 序列
  • 表(序列)

身份

IDENTITY类型(包括在SQL:2003标准中)受以下支持:

  • SQL服务器
  • MySQL(AUTO_INCREMENT)
  • DB2
  • 数据库

IDENTITY生成器允许按需自动增加integer / bigint列。 增量过程发生在当前正在运行的事务之外,因此回滚可能最终丢弃已分配的值(可能会发生值差距)。

增量过程非常有效,因为它使用了数据库内部的轻量级锁定机制,而不是重量级的事务性过程粒度锁定。

唯一的缺点是我们无法在执行INSERT语句之前知道新分配的值。 这种限制阻碍了Hibernate采用的“事务后写”刷新策略。 因此,Hibernates使用IDENTITY生成器禁用对实体的JDBC批处理支持。

对于以下示例,我们将启用会话工厂JDBC批处理:

properties.put("hibernate.order_inserts", "true");
properties.put("hibernate.order_updates", "true");
properties.put("hibernate.jdbc.batch_size", "2");

让我们使用IDENTITY生成策略定义一个实体:

@Entity(name = "identityIdentifier")
public static class IdentityIdentifier {@Id@GeneratedValue(strategy = GenerationType.IDENTITY)private Long id;
}

持续存在5个实体:

doInTransaction(new TransactionCallable<Void>() {@Overridepublic Void execute(Session session) {for (int i = 0; i < 5; i++) {session.persist(new IdentityIdentifier());}session.flush();return null;}
});

将在另一个查询之后执行一个查询(不涉及JDBC批处理):

Query:{[insert into identityIdentifier (id) values (default)][]}
Query:{[insert into identityIdentifier (id) values (default)][]}
Query:{[insert into identityIdentifier (id) values (default)][]}
Query:{[insert into identityIdentifier (id) values (default)][]}
Query:{[insert into identityIdentifier (id) values (default)][]}

除了禁用JDBC批处理之外,IDENTITY生成器策略不适用于每个具体类继承模型的Table ,因为可能存在多个具有相同标识符的子类实体,并且基类查询最终将检索具有相同标识符的实体(甚至(如果属于不同类型)。

序列

SEQUENCE生成器(在SQL:2003标准中定义)受以下支持:

  • 甲骨文
  • SQL服务器
  • PostgreSQL的
  • DB2
  • 数据库

SEQUENCE是一个数据库对象,它在每个连续的请求上生成增量整数。 SEQUENCES比IDENTIFIER列灵活得多,因为:

  • SEQUENCE是无表的,并且可以将同一序列分配给多个列或表
  • SEQUENCE可以预分配值以提高性能
  • SEQUENCE可以定义一个增量步骤,使我们可以受益于“池化” Hilo算法
  • SEQUENCE不会限制Hibernate JDBC批处理
  • SEQUENCE不会限制Hibernate继承模型

让我们使用SEQUENCE生成策略定义一个实体:

@Entity(name = "sequenceIdentifier")
public static class SequenceIdentifier {@Id@GenericGenerator(name = "sequence", strategy = "sequence", parameters = {@org.hibernate.annotations.Parameter(name = "sequenceName", value = "sequence"),@org.hibernate.annotations.Parameter(name = "allocationSize", value = "1"),})@GeneratedValue(generator = "sequence", strategy=GenerationType.SEQUENCE)private Long id;
}

我使用了“序列”生成器,因为我不希望Hibernate代表我们选择SequenceHiLoGenerator或SequenceStyleGeneGenerator 。

添加5个实体:

doInTransaction(new TransactionCallable<Void>() {@Overridepublic Void execute(Session session) {for (int i = 0; i < 5; i++) {session.persist(new SequenceIdentifier());}session.flush();return null;}
});

生成以下查询:

Query:{[call next value for hibernate_sequence][]}
Query:{[call next value for hibernate_sequence][]}
Query:{[call next value for hibernate_sequence][]}
Query:{[call next value for hibernate_sequence][]}
Query:{[call next value for hibernate_sequence][]}
Query:{[insert into sequenceIdentifier (id) values (?)][1]} {[insert into sequenceIdentifier (id) values (?)][2]}
Query:{[insert into sequenceIdentifier (id) values (?)][3]} {[insert into sequenceIdentifier (id) values (?)][4]}
Query:{[insert into sequenceIdentifier (id) values (?)][5]}

该表中的插入是批量处理的,但是我们知道在插入实体之前有5个序列调用。 这可以通过使用HILO算法进行优化。

表(序列)

生成序列还有另一种与数据库无关的替代方法。 一个或多个表可用于保存标识符序列计数器。 但这意味着要牺牲写入性能来实现数据库的可移植性。

尽管IDENTITY和SEQUENCES没有事务,但是使用数据库表授权ACID来同步多个并发id生成请求。

通过使用行级锁定,这比IDENTITY或SEQUENCE生成器要高得多的成本,使之成为可能。

必须在单独的数据库事务中计算序列,这需要IsolationDelegate机制,该机制同时支持本地(JDBC)和全局(JTA)事务。

  • 对于本地事务,它必须打开一个新的JDBC连接,因此对当前的连接池机制施加了更大的压力。
  • 对于全局事务,它需要挂起当前正在运行的事务。 在生成序列值之后,必须恢复实际事务。 此过程有其自己的成本,因此可能会影响整体应用程序性能。

让我们使用TABLE生成策略定义一个Entity:

@Entity(name = "tableIdentifier")
public static class TableSequenceIdentifier {@Id@GenericGenerator(name = "table", strategy = "enhanced-table", parameters = {@org.hibernate.annotations.Parameter(name = "table_name", value = "sequence_table")})@GeneratedValue(generator = "table", strategy=GenerationType.TABLE)private Long id;
}

我使用了较新的“增强表”生成器,因为旧式“表”生成器已被弃用。

添加5个实体:

doInTransaction(new TransactionCallable<Void>() {@Overridepublic Void execute(Session session) {for (int i = 0; i < 5; i++) {session.persist(new TableSequenceIdentifier());}session.flush();return null;}
});

生成以下查询:

Query:{[select tbl.next_val from sequence_table tbl where tbl.sequence_name=? for update][default]}
Query:{[insert into sequence_table (sequence_name, next_val)  values (?,?)][default,1]}
Query:{[update sequence_table set next_val=?  where next_val=? and sequence_name=?][2,1,default]}
Query:{[select tbl.next_val from sequence_table tbl where tbl.sequence_name=? for update][default]}
Query:{[update sequence_table set next_val=?  where next_val=? and sequence_name=?][3,2,default]}
Query:{[select tbl.next_val from sequence_table tbl where tbl.sequence_name=? for update][default]}
Query:{[update sequence_table set next_val=?  where next_val=? and sequence_name=?][4,3,default]}
Query:{[select tbl.next_val from sequence_table tbl where tbl.sequence_name=? for update][default]}
Query:{[update sequence_table set next_val=?  where next_val=? and sequence_name=?][5,4,default]}
Query:{[select tbl.next_val from sequence_table tbl where tbl.sequence_name=? for update][default]}
Query:{[update sequence_table set next_val=?  where next_val=? and sequence_name=?][6,5,default]}
Query:{[insert into tableIdentifier (id) values (?)][1]} {[insert into tableIdentifier (id) values (?)][2]}
Query:{[insert into tableIdentifier (id) values (?)][3]} {[insert into tableIdentifier (id) values (?)][4]}
Query:{[insert into tableIdentifier (id) values (?)][5]}

表生成器允许JDBC批处理,但它依靠SELECT FOR UPDATE查询。 行级别锁定绝对比使用本机IDENTITY或SEQUENCE效率低。

因此,根据您的应用程序要求,您可以选择多个选项。 没有一个单一的获胜策略,每一个都有优点和缺点。

  • 代码可在GitHub上获得 。

翻译自: https://www.javacodegeeks.com/2014/07/hibernate-identity-sequence-and-table-sequence-generator.html

休眠身份,序列和表(序列)生成器相关推荐

  1. hibernate 序列_Hibernate身份,序列和表(序列)生成器

    hibernate 序列 介绍 在上一篇文章中,我谈到了不同的数据库标识符策略. 这篇文章将比较最常见的替代主要关键策略: 身份 序列 表(序列) 身份 IDENTITY类型(包括在SQL:2003标 ...

  2. oracle 用序列插入表,Oracle序列的使用与说明

    1.序列的创建与说明 创建序列,Oracle序列的语法格式为:CREATE SEQUENCE 序列名[INCREMENT BY n][START WITH n][{MAXVALUE/ MI 1.序列的 ...

  3. 扩增子分析解读4去嵌合体,非细菌序列,生成代表性序列和OTU表

    写在前面 之前发布的<扩增子图表解读>系列,相信关注过我的朋友大部分都看过了(链接直达7月文章目录).这些内容的最初是写本实验室的学生们学习的材料,加速大家对同行文章的解读能力. < ...

  4. JSON序列——主从表查询

    JSON序列--主从表查询 客户端代码: procedure TForm1.Button4Click(Sender: TObject); // 主从表 查询 beginvar url: TynUrl ...

  5. oracle数据库新建表增加表序列,设置id自增

    1,oracle数据库增加新表时,设置表id为自增 最小1 最大9999999999 CREATE SEQUENCE "数据库名称"."SEQ_表名称" MIN ...

  6. Mysql实战之快速填充序列维度表

    Mysql实战案例五之快速填充序列维度表 1.需求 2.代码 3.执行效果 4. create table nums( a int UNSIGNED not null primary key )eng ...

  7. 波表序列合成器:KORG Wavestate Native Mac

    Korg 很自豪地推出 wavestate native,它是与硬件 wavestate 合成器完全兼容的软件对应物.wavestate native 在 macOS 和 Windows 上以 VST ...

  8. oracle给一个表创建序列,oracle表中怎么创建序列

    oracle序列的创建: create sequence seq_newsId increment by 1 start with 1 maxvalue 999999999; 获得oracle序列的S ...

  9. oracle序列累加循环,Oracle 序列的使用与说明

    1.序列的创建与说明 创建序列,Oracle序列的语法格式为: CREATE SEQUENCE 序列名 [INCREMENT BY n] [START WITH n] [{MAXVALUE/ MINV ...

最新文章

  1. Java Tread多线程(0)一个简单的多线程实例
  2. 密码与安全新技术总结
  3. 你要了解的11款面向Linux系统的一流备份实用工具
  4. Flutter AnimatedList 使用解析
  5. RHEL5.0 搭建DNS服务器
  6. 十年前开发的平板游戏:HyllCube 三维四子棋游戏,获得了全国一等奖
  7. 嗯,好不容易得到面试机会,面试官问的全回答了,但心痒一看状态进了人才库了.....
  8. Indilinx主控固态量产成功修复步骤
  9. EasyNVR网页Chrome无插件播放摄像机视频功能二次开发之云台控制接口示例代码
  10. Android 第三方SDK的检测与提取
  11. DbVisualizer破解
  12. Fabric CA/数字证书管理
  13. python获取数组长度_Python返回数组(List)长度的方法
  14. 一个程序员修炼之道《论程序员的自我修养》
  15. 华三交换机使用U盘导入/出配置文件
  16. 数据中台数据分析过程梳理
  17. SpringBoot如何配置log4j输出日志呢?
  18. python实时股票数据折线图_如何用python获取实时的股票数据?
  19. Flutter 使用环信即时通讯闪退解决办法
  20. Java程序设计教程与实训_Java程序设计教程与项目实训

热门文章

  1. 手把手教会你(单/多)文件上传(并修改文件默认的最大最小值)
  2. 用idea添加一个模块
  3. Map的两种遍历方法
  4. spring boot建立项目 git推送giteee
  5. delphi dll是否可用var参数_时间序列之向量自回归(VAR)学习重点
  6. 转:聊聊开发中幂等性问题(*)
  7. java安全——类加载器+字节码校验+安全管理器与访问权限
  8. Spring Hibernate教程
  9. java 示例_功能Java示例 第4部分–首选不变性
  10. 为什么非阻塞io性能更好_提高性能:流的非阻塞处理