新功能(3.2.3)Hibernate标识符生成器

发布者:    |      

介绍...

从3.2.3版本开始,我增加了两个新的标识符生成器,旨在提高可移植性。它们在可移植性方面的处理方式与旧的“本地”生成器不同。通常来说,使用合成标识符生成策略的同时考虑可移植性,实际上只是希望拥有序列提供的功能,即使数据库可能不支持序列。请注意,我明确排除了IDENTITY风格的生成器,因为通常来说,对象/关系映射技术将更倾向于标识符生成策略,其中标识符值可以在执行(且无需实际执行)插入语句之前检索;这对于Hibernate和其他“事务后写”技术来说确实是如此,因为在IDENTITY列的情况下,插入必须立即执行(此外,由于JDBC没有定义检索批量IDENTITY生成值的机制,因此对于使用IDENTITY生成器的实体,批处理必须隐式禁用),从而绕过了“事务后写”行为。

这两个生成器是

  • org.hibernate.id.enhanced.SequenceStyleGenerator - 它在可移植性方面的处理方式是,实际上你并不关心是否在数据库中实际使用SEQUENCE;你只是想要类似序列的值生成。在支持SEQUENCES的数据库中,SequenceStyleGenerator实际上将使用SEQUENCE作为值生成器;对于不支持SEQUENCES的数据库,它将使用一个单行表作为值生成器,但具有与SEQUENCE值生成器完全相同的特征(即它始终在单独的事务中处理“序列表”)。
  • org.hibernate.id.enhanced.TableGenerator - 虽然并非专门针对可移植性,但TableGenerator当然可以在所有数据库中使用。它使用一个多行表,行通过一个(可配置的)sequence_name列进行索引;一个方法是为每个实体在表中定义一个唯一的sequence_name值以分隔其标识符值。它是从旧的org.hibernate.id.MultipleHiLoPerTableGenerator发展而来的,并使用了基本上相同的表结构。然而,虽然MultipleHiLoPerTableGenerator在值生成上固有地应用了hi-lo算法,但这个新的TableGenerator被添加是为了能够利用可插拔的优化器。

这两个生成器除了其他特定参数外,还共享3个有用的配置参数

  • 优化器
  • 初始值
  • 增量大小

优化器的作用是限制我们实际上需要击中数据库的次数,以确定下一个标识符值。initial_value和increment_size的确切效果取决于选择的优化器。优化器提供了3个选项

  • 无 - 表示在每次请求时都击中数据库
  • hilo - 表示使用内存中的池化技术,这与旧的Hibernate hiloseqhilo生成器的基本逻辑相同。在数据库值方面,它们逐个增加;换句话说,increment_size适用于内存算法
  • 池化 - 表示使用存储的池化技术。与hilo不同,其中增量值存储和检索自数据库序列/表,pool存储实际的当前hi值到数据库中。例如,假设increment_size=10

底层实现

所以一般来说,hilo和池化优化器都试图通过最小化我们需要击中数据库的次数来优化性能。太好了!那么,它们到底有什么不同呢?让我们看看数据库中存储的值,以此来说明区别。

优化器=hilo (增量大小=10)

在初始请求之后,我们将有

|  value (db)  |  value (in-memory)  |  hi (in-memory)  |
| 1            | 1                   | 11               |

数据库值和hi将保持不变,直到第12次请求,此时我们将溢出

|  value (db)  |  value (in-memory)  |  hi (in-memory)  |
| 2            | 12                  | 21               |

基本上,hi定义了溢出值;一旦内存中的值达到hi值,我们就需要击中数据库并定义一个新的值范围。这种方法的主要缺点是当与需要插入值的旧版应用程序一起使用时;那些其他应用程序也必须理解并使用此hilo算法。

优化器=池化 (增量大小=10)

在初始请求之后,我们将有

|  value (db)  |  value (in-memory)  |  hi (in-memory)  |
| 11           | 1                   | 11               |

数据库值和hi将保持不变,直到第12次请求,此时我们将溢出

|  value (db)  |  value (in-memory)  |  hi (in-memory)  |
| 21           | 12                  | 31               |

如您所见,使用此优化器时,increment_size实际上编码到数据库值中。这对于支持序列的数据库来说非常完美,因为通常它们还定义了一个创建序列时的/INCREMENT BY/选项,以便调用获取下一个序列值自动应用正确的increment_size。即使其他应用程序也在插入值,我们也会完全安全,因为序列本身将处理应用此increment_size。实际上,如果SequenceStyleGenerator在这种情况下由于时钟溢出而回退到使用表,那么也会是安全的。

结论

我预计这两个新生成器实际上会在缩略名方面取代现有的生成器。具体来说,我预计

  • sequence背后的实现将从org.hibernate.SequenceGenerator更改为新的org.hibernate.id.enhanced.SequenceStyleGenerator
  • table背后的实现将从org.hibernate.TableGenerator更改为新的org.hibernate.id.enhanced.TableGenerator

第二个替换更具风险,因为两者之间有很大的不同。但我们始终反对直接使用当前的table生成器,所以我认为在那里应该是安全的。我仍然不确定何时进行替换(可能是4.0?),但在此期间,新生成器可用,并且强烈推荐使用。


返回顶部