我已经用Hibernate,PostgreSQL和Spring设置了一个测试应用程序,并且我一直遇到这个无法解释的错误。我希望这里的人可以阐明这个问题。
我的实体看起来像这样:
@Entity
@Table(name = "something")
public class Something {
@Id
@SequenceGenerator(name = "somethingGen", sequenceName = "something_id_seq", allocationSize = 30)
@GeneratedValue(strategy = GenerationType.SEQUENCE, generator = "somethingGen")
@Column(name = "id", unique = true, nullable = false)
private long id;
public Something() {
}
public long getId() {
return id;
}
@Override
public String toString() {
return new StringJoiner(", ", Something.class.getSimpleName() + "[", "]")
.add("id=" + id)
.toString();
}
}
出于测试目的,我创建了一个Spring Data Repository,插入了五个条目并将其取回:
System.out.println("starting...");
for (int i = 0; i < 5; i++) {
repository.save(new Something());
}
repository.findAll().forEach(System.out::println);
我第一次启动此代码时,它几乎可以按预期工作:
Something[id=1]
Something[id=2]
Something[id=3]
Something[id=4]
Something[id=5]
但是第二次出现此异常:org.hibernate.MappingException: The increment size of the [something_id_seq] sequence is set to [30] in the entity mapping while the associated database sequence increment size is [1].
所以我检查了Postgres DB中的序列:
uat=# \d something_id_seq
Sequence "public.something_id_seq"
Column | Type | Value
---------------+---------+---------------------
sequence_name | name | something_id_seq
last_value | bigint | 1
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
这是第一个问题。似乎Hibernate正在使用错误的增量值创建序列。因此,我更改了crement_by值:alter sequence something_id_seq increment 30
,然后再次启动我的代码,最终得到以下输出:
Something[id=1]
Something[id=2]
Something[id=3]
Something[id=4]
Something[id=5]
Something[id=901]
Something[id=902]
Something[id=903]
Something[id=904]
Something[id=905]
现在序列看起来像这样:
---------------+---------+---------------------
sequence_name | name | something_id_seq
last_value | bigint | 31
start_value | bigint | 1
increment_by | bigint | 30
所以在我看来,新ID是通过increment_by * allocation_size + last_value
计算出来的,但是我一直怀疑新ID是30(allocation_size * last_value
),因为我怀疑increment_by
和{{ 1}}由于MappingException而异。
这给我留下了两个问题:
我期望id分别为0、30、60、90 ...,而最终我得到的id分别为1和900。SequenceGenerator的javadoc指出,distributionSize为allocationSize
。这是否意味着the amount to increment by when allocating sequence numbers from the sequence
和increment_by
不是同一个人?他们如何联系在一起(例如,为什么我看到allocationSize
?如何实现预期的行为?
MappingException向我表明Hibernate正在使用错误的增量值创建序列。如何让Hibernate创建正确的主机?
我正在使用Hibernate 5.4.2.Final和PostgreSql 9.6.12以及以下设置:
MappingException
我怀疑问题可能出在HiLo发生器上,但我一生都无法解决:
HibernateJpaVendorAdapter hibernateJpaVendorAdapter = new HibernateJpaVendorAdapter();
hibernateJpaVendorAdapter.setDatabase(Database.POSTGRESQL);
hibernateJpaVendorAdapter.setDatabasePlatform(PostgreSQL9Dialect.class.getName());
hibernateJpaVendorAdapter.setGenerateDdl(true);
答案 0 :(得分:0)
increment_by
和allocationSize
的大小必须相同。但是,除非您有一个分布式的重插入系统,否则应该使用默认的increment_by
为1,并使用@GeneratedValue(strategy = GenerationType.IDENTITY)
。
由于各种保留ID的线程,但是插入失败后,您可能最终跳到900。我有那个问题。现在,我插入IDENTITY
。
对于MappingException,something_id_seq
序列由postgres自动创建,因为PostgreSQL的方言在创建表时使用serial
或bigserial
。参见PostgreSQL81IdentityColumnSupport。也许应该将其视为Hibernate不会更改allocationSize
的顺序的错误,您可以进行报告。