java – 数据库和JPA中的不同PostgreSQL序列ID
我真的很困惑……但首先,让我给你一个粗略的概述.
我已经在数据库中进行了一些重组,将4个表合并为两个.所有表都有简单的数字序列作为主键.事实上,这些表非常(非常)相似.它们被分成两部分的唯一原因是基于必须导入的历史数据.没有这种分裂,就会有很多冗余,从概念上讲它是有道理的. 现在,经过大量的工作进入数据清理后,现在终于可以将它们合并,只需使用其中一个字段作为鉴别器.谈论不那么抽象,表格包含公司.他们要么是当地居民,要么不是(两个班级).可以通过邮政编码(鉴别字段)轻松区分它们.这些表是缓慢变化的维度(序列是代理键).其他两个表包含附加到这些SCD的正常数据.因此,4桌. 2为本地公司,2为非本地公司. 这些表现在已经简化和合并,所以我现在只有Company和CompanyData. 为了安全起见,并且不丢失任何历史信息,我创建了两个带有新序列字段的新表.旧的序列保存10年后我意识到出了问题;) 到现在为止还挺好. 重组相当容易,重新连接正确的条目也是一个明智的选择.接下来,我需要更新与此DB接口的应用程序,这是一项更多的工作,但仍然很容易.该应用程序使用JPA,使用EclipseLink 2.0 – 如上所述 – 一个PostgreSQL 9.0数据库. 这里出现了奇怪的部分: 当我尝试插入新公司时,我收到重复的密钥错误,说明已存在给定的ID.但这应该由序列对象处理……如果不是吗? 所以我做了一些挖掘.我可以验证后续的inerts确实返回了带有递增ID的重复键错误.这意味着序列逻辑正常.唯一的问题是当前值太低.因此,调用nextval(或JPA使用的任何内容)将返回已存在的ID. 我在JPA-Entity中有以下内容: @Id @GeneratedValue(strategy = GenerationType.SEQUENCE,generator = "enterprise_id_seq") @Column(name = "id",nullable = false) private Integer id; 我的序列看起来像这样: test_db=# d enterprise_id_seq Sequence "public.enterprise_id_seq" Column | Type | Value ---------------+---------+--------------------- sequence_name | name | enterprise_id_seq last_value | bigint | 19659 start_value | bigint | 1 increment_by | bigint | 1 max_value | bigint | 9223372036854775807 min_value | bigint | 1 cache_value | bigint | 1 log_cnt | bigint | 32 is_cycled | boolean | f is_called | boolean | t 我得到的错误是: [...] Caused by: Exception [EclipseLink-4002] (Eclipse Persistence Services - 2.0.1.v20100213- r6600): org.eclipse.persistence.exceptions.DatabaseException Internal Exception: org.postgresql.util.PSQLException: ERROR: duplicate key value violates unique constraint "enterprise_pkey" Detail: Key (id)=(19611) already exists. Error Code: 0 Call: INSERT INTO en... [...] 如您所见,它尝试插入一个ID为19611的实体,但该序列的最后一个值是19659.这显然是错误的. 我还尝试重新启动所有这些后面的应用程序服务器,以关闭所有打开的连接和会话.没有运气……我注意到的另一件事:该字段被定义为整数.它应该更长吗?这将需要在代码中进行相当多的更改,我还没有时间来解决这个问题. 由于我只有50个条目,我可以简单地尝试运行插入50次,但我更确切地知道出了什么问题…… 我在这里错过了什么? 更新:经过一些挖掘后,我遇到了allocationSize,其默认值为50.有趣的是,这与我看到的ID的差异非常接近.由于某些测试和毛躁,它可能不是100%相同.它有关系吗?老实说,我还没有理解这个背景背后的想法…… 解决方法
当然对于Hibernate,默认情况下使用GenerationType.SEQUENCE是使用hi / lo策略,在数据库返回的值之前最多使用allocationSize id.将allocationSize设置为1,它应该是DTRT.
以前对一个非常类似的问题的答案:Hibernate generating two different sequence Ids for PostgreSQL insert (编辑:李大同) 【声明】本站内容均来自网络,其相关言论仅代表作者个人观点,不代表本站立场。若无意侵犯到您的权利,请及时与联系站长删除相关内容! |