休眠,@SequenceGenerator和allocationSize(Hibernate, @S

2019-06-18 11:09发布

使用时,我们都知道Hibernate的默认行为@SequenceGenerator -它由一个增加实际的数据库序列,由50(默认多个该值allocationSize值) -然后使用这个值作为实体ID。

这是不正确的行为,并与冲突规范它说:

allocationSize - (可选)的量由从所述序列分配序列号时递增。

需要明确的是:我不操心生成的ID之间的差距。

我关心的是与底层数据库序列完全一致的ID。 例如:任何其他应用程序(例如,使用纯JDBC)可能需要插入下从序列获得的ID新行 - 但所有这些值可能已被使用由Hibernate! 疯狂。

难道有人知道任何解决这个问题(没有设置allocationSize=1 ,从而降低性能)?

编辑:
为了把事情说清楚。 如果最后插入的记录有ID = 1 ,则HB使用价值51, 52, 53...它的新的实体,但在同一时间:序列的数据库中的值将被设置为2 。 它可以在其他应用程序正在使用该序列容易导致错误。

在行吟诗人的手:规范说(在我的理解),该数据库序列应该被设置为51 ,并在此期间HB应该从范围使用值2, 3 ... 50


更新:
正如史蒂夫埃伯索尔提到如下:由我所描述的行为(以及许多最直观的),可以通过设置启用hibernate.id.new_generator_mappings=true

谢谢大家。

更新2:
对于未来的读者,下面你可以找到工作的例子。

@Entity
@Table(name = "users")
public class User {

    @Id
    @GeneratedValue(strategy = GenerationType.SEQUENCE, generator = "USERS_SEQ")
    @SequenceGenerator(name = "USERS_SEQ", sequenceName = "SEQUENCE_USERS")
    private Long id;
}

persistence.xml中

<persistence-unit name="testPU">
  <properties>
    <property name="hibernate.id.new_generator_mappings" value="true" />
  </properties>
</persistence-unit>

Answer 1:

为了绝对清楚...你的描述以任何方式规范冲突。 关于价值观的规范会谈休眠分配到相应的实体,没有实际存储在数据库中的序列值。

但是,让你正在寻找的行为的选项。 第一眼看到我的回答上是有办法使用JPA注释动态选择@GeneratedValue战略和Hibernate? 这会给你的基础知识。 只要你设置为使用SequenceStyleGenerator,Hibernate会解释allocationSize使用在SequenceStyleGenerator了“集中优化”。 该“汇集优化”是与数据库,允许在创建序列的“增量”选项(不支持序列的所有数据库支持增量)使用。 总之,阅读了有关各种优化策略存在。



Answer 2:

allocationSize=1这是获得查询休眠前的微优化试图在allocationSize的范围分配值和因此要尽量避免对序列查询数据库。 但这种查询将每一个,如果你把它设置为1,这几乎没有什么差别,因为如果你的数据库是通过一些其他的应用程序访问,如果相同的ID被其它应用程序同时的话就会产生问题时执行。

下一代序列标识是基于allocationSize。

通过defualt它保持为50这实在是太多了。 它也将只有当你将拥有近约帮助50在一次会议记录中没有坚持并且将使用这一特定会话和TRANSATION被持久化。

所以,你应该始终使用allocationSize=1 ,而使用SequenceGenerator 。 作为最下层的数据库序列总是递增1



Answer 3:

史蒂夫埃伯索尔和其他成员,
请您帮着解释有较大的差距(默认为50)的ID的原因是什么? 我使用Hibernate的4.2.15,发现org.hibernate.id.enhanced.OptimizerFactory中国社会科学院下面的代码。

if ( lo > maxLo ) {
   lastSourceValue = callback.getNextValue();
   lo = lastSourceValue.eq( 0 ) ? 1 : 0;
   hi = lastSourceValue.copy().multiplyBy( maxLo+1 ); 
}  
value = hi.copy().add( lo++ );

当它击中的if语句内,喜价值越来越大很多。 所以,随着频繁的重启服务器在测试过程中我的ID生成以下顺序ID:
1,2,3,4,19,250,251,252,400,550,750,751,752,850,1100,1150。

我知道你已经表示,它不与规范相冲突,但我相信这将是大多数开发者非常难以预料的情况。

任何人的输入会更加有帮助。

Jihwan

UPDATE:ne1410s:感谢您的编辑。
cfrick:OK。 我去做。 这是我在这里的第一篇文章,是不知道如何使用它。

现在,我更好地理解为什么器MAX10用于两个目的:因为休眠调用DB序列一次,不断加大对Java级别的ID,并将其保存到数据库,值的Java水平ID应该考虑多少,而不调用被改变当它调用序列下次DB序列。

例如,序列ID是1在一个点和休眠进入5,6,7,8,9(带allocationSize = 5)。 下一次,当我们得到一个序列号,DB返回2,但是Hibernate需要使用10,11,12 ...所以,这就是为什么 “HI = lastSourceValue.copy()。multiplyBy(器MAX10 + 1)” 是用于获取下一个ID从数据库序列返回10从2。 看来只有困扰的事情是经常重新启动服务器时,这是我的问题与差距较大。

所以,当我们使用该序列号,在表中插入的ID将不匹配与数据库中的序列号。



Answer 4:

挖进入休眠源代码和下面配置后进入到Oracle分贝为50个后插入下一个值。 因此,请在每次调用时您INST_PK_SEQ增量50。

休眠5用于以下策略

还检查下面http://docs.jboss.org/hibernate/orm/5.1/userguide/html_single/Hibernate_User_Guide.html#identifiers-generators-sequence

@Id
@Column(name = "ID")
@GenericGenerator(name = "INST_PK_SEQ", 
strategy = "org.hibernate.id.enhanced.SequenceStyleGenerator",
parameters = {
        @org.hibernate.annotations.Parameter(
                name = "optimizer", value = "pooled-lo"),
        @org.hibernate.annotations.Parameter(
                name = "initial_value", value = "1"),
        @org.hibernate.annotations.Parameter(
                name = "increment_size", value = "50"),
        @org.hibernate.annotations.Parameter(
                name = SequenceStyleGenerator.SEQUENCE_PARAM, value = "INST_PK_SEQ"),
    }
)
@GeneratedValue(strategy = GenerationType.SEQUENCE, generator = "INST_PK_SEQ")
private Long id;


Answer 5:

我会检查的DDL为架构中的序列。 JPA实现是正确的分配大小的顺序只负责创作。 因此,如果分配大小是50那么你的序列必须具有50在其DDL的增量。

这种情况下,通常可以与创建的序列与分配尺寸1再后来被配置为分配大小50(或默认),但不更新DDL的序列发生。



文章来源: Hibernate, @SequenceGenerator and allocationSize