【问题标题】:How does increment_by of a PostgreSQL sequence work with the allocationSize of Hibernate?PostgreSQL 序列的 increment_by 如何与 Hibernate 的 allocationSize 一起工作?
【发布时间】:2019-08-19 09:52:45
【问题描述】:

我已经使用 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 正在创建具有错误增量值的序列。所以我更改了 increment_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_byallocationSize 是同一件事因为 MappingException。

这给我留下了两个问题:

  1. 我预计 id 大约是 0、30、60、90...,但我最终得到的 id 大约是 1 和 900。SequenceGenerator 的 javadoc 指出 allocationSize 是 the amount to increment by when allocating sequence numbers from the sequence。这是否意味着increment_byallocationSize 不是一回事?它们是如何联系在一起的(例如,为什么我会看到 MappingException)以及如何实现预期的行为?

  2. MappingException 向我表明 Hibernate 正在创建具有错误增量值的序列。如何让 Hibernate 创建正确的?

我正在使用 Hibernate 5.4.2.Final 和 PostgreSql 9.6.12 以及这些设置:

HibernateJpaVendorAdapter hibernateJpaVendorAdapter = new HibernateJpaVendorAdapter();
hibernateJpaVendorAdapter.setDatabase(Database.POSTGRESQL);
hibernateJpaVendorAdapter.setDatabasePlatform(PostgreSQL9Dialect.class.getName());
hibernateJpaVendorAdapter.setGenerateDdl(true);

我怀疑问题可能出在 HiLo 生成器的某个地方,但对于我来说,我无法弄清楚:

hibernate.id.new_generator_mappings=true
hibernate.id.optimizer.pooled.preferred=hilo
hibernate.schema_update.unique_constraint_strategy=RECREATE_QUIETLY

【问题讨论】:

    标签: java postgresql hibernate orm hibernate-mapping


    【解决方案1】:

    increment_byallocationSize 需要具有相同的大小。但是,除非您有一个分布式插入繁重的系统,否则您应该使用默认的 increment_by 1,并使用 @GeneratedValue(strategy = GenerationType.IDENTITY)

    您可能最终会跳转到 900,因为各种线程保留了 id,但随后插入失败。我有那个问题。现在我插入IDENTITY

    至于 MappingException,something_id_seq 序列是 postgres 自动创建的,因为 PostgreSQL 方言在创建表时使用了serialbigserial。见PostgreSQL81IdentityColumnSupport。也许应该认为是Hibernate没有将序列更改为allocationSize的bug,您可以报告它。

    【讨论】:

    • 我没有使用任何线程。上面的示例代码实际上是应用程序的全部代码。我不认为该序列是由 PostgreSQL 生成的,因为正在记录 create 语句,如果我没有使用 HiLo,那么增量是正确的。
    猜你喜欢
    • 2012-05-25
    • 2013-05-15
    • 1970-01-01
    • 2012-01-25
    • 2012-03-04
    • 2012-04-13
    • 1970-01-01
    • 2015-05-19
    • 1970-01-01
    相关资源
    最近更新 更多