使用时,我们都知道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>
为了绝对清楚...你的描述不以任何方式规范冲突。 关于价值观的规范会谈休眠分配到相应的实体,没有实际存储在数据库中的序列值。
但是,让你正在寻找的行为的选项。 第一眼看到我的回答上是有办法使用JPA注释动态选择@GeneratedValue战略和Hibernate? 这会给你的基础知识。 只要你设置为使用SequenceStyleGenerator,Hibernate会解释allocationSize
使用在SequenceStyleGenerator了“集中优化”。 该“汇集优化”是与数据库,允许在创建序列的“增量”选项(不支持序列的所有数据库支持增量)使用。 总之,阅读了有关各种优化策略存在。
allocationSize=1
这是获得查询休眠前的微优化试图在allocationSize的范围分配值和因此要尽量避免对序列查询数据库。 但这种查询将每一个,如果你把它设置为1,这几乎没有什么差别,因为如果你的数据库是通过一些其他的应用程序访问,如果相同的ID被其它应用程序同时的话就会产生问题时执行。
下一代序列标识是基于allocationSize。
通过defualt它保持为50
这实在是太多了。 它也将只有当你将拥有近约帮助50
在一次会议记录中没有坚持并且将使用这一特定会话和TRANSATION被持久化。
所以,你应该始终使用allocationSize=1
,而使用SequenceGenerator
。 作为最下层的数据库序列总是递增1
。
史蒂夫埃伯索尔和其他成员,
请您帮着解释有较大的差距(默认为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将不匹配与数据库中的序列号。
挖进入休眠源代码和下面配置后进入到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;
我会检查的DDL为架构中的序列。 JPA实现是正确的分配大小的顺序只负责创作。 因此,如果分配大小是50那么你的序列必须具有50在其DDL的增量。
这种情况下,通常可以与创建的序列与分配尺寸1再后来被配置为分配大小50(或默认),但不更新DDL的序列发生。