PostgreSQL序列的increment_by如何与Hibernate的allocationSize一起使用?

问题描述 投票:1回答:1

我已经使用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. 我预计ids大约在0,30,60,90 ...而且我最终得到了大约1和900的ID.SequenceGenerator的javadoc声明allocationSize是the amount to increment by when allocating sequence numbers from the sequence。这是否意味着increment_byallocationSize不是一回事?它们如何结合在一起(例如,为什么我看到MappingException)以及如何实现我期望的行为?
  2. MappingException向我表明Hibernate正在创建具有错误增量值的序列。如何让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个回答
0
投票

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

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

对于MappingException,something_id_seq序列由postgres自动创建,因为PostgreSQL方言在创建表时使用serialbigserial。见PostgreSQL81IdentityColumnSupport。也许它应该被认为是一个错误,Hibernate不会改变allocationSize的序列,你可以报告它。

© www.soinside.com 2019 - 2024. All rights reserved.