Hibernate generating two different sequence Ids for PostgreSQL insert
Asked Answered
G

1

6

I have an entity defined with a sequence-generated primary key:

@Id
@GeneratedValue(strategy = GenerationType.SEQUENCE, generator = "id_key_gen")
@SequenceGenerator(name = "id_key_gen", sequenceName = "id_key_seq")
@Column(name = "id", unique = true, nullable = false)
public int getId() {
    return this.id;
}

I'm using PostgreSQL, and this key is defined as a serial. According to PostgreSQL

select last_value from id_key_seq;

returns

1603.

When I do a create() to persist an instance of this entity, I'm seeing the following in my logs (unrelated stuff edited out):


05 15:15:26.948 org.hibernate.id.enhanced.SequenceStructure [DEBUG] - Sequence value obtained: 1604

05 15:15:26.948 org.hibernate.event.def.AbstractSaveEventListener [DEBUG] - generated identifier: 1554, using strategy: org.hibernate.id.enhanced.SequenceStyleGenerator


Subsequent SQL insert statements refer to the value 1554, not what it should be using, 1604 (based on the value returned from the SequenceStructure. Where did Hibernate get 1554 from?

Seems to me Hibernate has a bug here - SequenceStructure knows the correct next value, but it isn't being used. Any idea how to resolve this?

FYI: I'm aware of this page, which says to use GenerationType.AUTO because the "Hibernate folks completely messed this up", but there isn't much beyond that not-very-helpful statement.

Grammer answered 5/1, 2011 at 21:35 Comment(0)
L
6

Looks like if you use GenerationType.SEQUENCE, you need to be specifying an "increment value" of 1 to avoid it using the sequence as a Hi/Lo seed.

The first answer (the useful one) to the question you posted explains that you need to specify "allocationSize=1" in the @GeneratedValue annotation.

On newer Hibernate releases you can instead set hibernate.id.new_generator_mappings=true in your Hibernate properties; see the docs.

Loney answered 5/1, 2011 at 22:54 Comment(4)
Thanks @araqnid, setting allocationSize to 1 does work, but I am curious about the comment that this approach is not "good practice".Grammer
setting allocationSize to 1 is a degenerate case, making a HiLo-style generator work as a normal sequence generator. OTOH, it's what you need, so use it. Looking at the code in Hibernate 3.5, the allocation size is used to pick an Optimizer implementation, so it's handled gracefully now.Loney
In my opinion, the Hibernate team needs to rethink their implementation of this; it's confusing and unnecessarily so. Setting allocationSize to 1 is exactly what I needed, but I wonder if this shouldn't be the default for SEQUENCE on PostgreSQL.Grammer
Better to set hibernate.id.new_generator_mappings which makes everything a bit saner.Gastroscope

© 2022 - 2024 — McMap. All rights reserved.