doque
doque

Reputation: 2733

JPA/Ebean - force @Id to strictly increment by +1 with PostgreSQL

I have the following Model:

public class Parameter extends Model {
    @Id
    @GeneratedValue(strategy = GenerationType.IDENTITY)
    public long id;
}

The records created by save() look like this:

play=> select id from parameter;
 id
----
  1
  2
  3
  4
  5
 21
(6 rows)

Is there a way that I can tell JPA to always increment the id by exactly one, instead of randomly jumping to 21?

Upvotes: 0

Views: 1439

Answers (3)

mesompi
mesompi

Reputation: 699

If you are using Oracle don't forget to add SequenceGenerator with an allocationSize of 1 :

    @Id
    @Column(name = "id")
    @GeneratedValue(strategy = GenerationType.SEQUENCE, generator = "mysequence")
    @SequenceGenerator(name = "mysequence", sequenceName = "mysequence", allocationSize = 1)
    private Long id;

Upvotes: 0

Rob Bygrave
Rob Bygrave

Reputation: 4031

What you are observing (jump to 21) is likely to be an implmentation detail of Ebean prior to 4.0.5. Ebean is using a 'fetch ahead' mechanism on the sequence. After 4.0.5 Ebean switched to use Postgres SERIAL by default (so by default you won't see this with Ebean/Postgres after 4.0.5). Refer: https://github.com/ebean-orm/avaje-ebeanorm/issues/97

That all said - 'incrementing EXACTLY by 1' is something you generally want to avoid as it becomes a concurrency issue (avoid making the autoincrement ID transactional as that introduces contention). When you need 'increment exactly by one' semantics (like cheque numbers etc) then you can look to create in batch in advance.

Upvotes: 1

siva636
siva636

Reputation: 16441

You should be able to achieve this by using @TableGenerator and allocationSize=1. An example code something like the following. You need to create a separate table to store the PK, additional work, but more portable than @GeneratedValue.

@TableGenerator(name="MAIN_PK_GEN", table="pk_gen", pkColumnName="GEN_NAME", valueColumnName="GEN_VALUE", pkColumnValue="MAIN_PK_GEN", allocationSize=1)
    @Id @GeneratedValue(strategy=GenerationType.TABLE, generator="MAIN_PK_GEN" )
    @Basic(optional = false)
    @Column(name = "PK")
    private Integer pk;

(But using allocationSize=1 may not be efficient)

See this tutorial for step by step explanation.

Upvotes: 0

Related Questions