tags:

views:

234

answers:

2

I have used the following id generation strategy for primary keys.

    @Id
        @GeneratedValue(strategy = IDENTITY)
        @Column(name = "id", unique = true, nullable = false, insertable = false, updatable = false)
        private Integer id;

I would like to do the same for a non primary key column. [a] What would be the semantics of defining an automatic generation scheme for such a key [b] Is there a guarantee that there will not be a gap in numbers for the generated number.

+3  A: 

If you remove the @Id annotation, and keep the rest (changing the field name of course), that should work.

    @GeneratedValue(strategy = IDENTITY)
    @Column(name = "columnName", unique = true, nullable = false, insertable = false, updatable = false)
    private Integer columnName;

By allowing the database to generate the column values you will ensure that there are no gaps, except in the case of deletes and rollbacks.

For instance, if you delete rows in the middle of your table, then that will create a gap that will not be filled.

James McMahon
Database don't provide this guarantee -- they only provide increasing unique number
ewernli
@ewernli, that is a good point, I have corrected my answer.
James McMahon
@James McMahon I am curious: Can i use @GeneratedValue(SEQUENCE) in some property other than a primary key, and its value will be generated ???
Arthur Ronald F D Garcia
@Arthur Ronald F D Garcia, Yes, I believe so. I don't have a lot of experience generating the database from JPA entity classes, as I usually create the database and then generate my entity classes based on that. This should work though, let me know if you find differently.
James McMahon
I tried the above suggestion many times on H2 and it seems to fail with a Hibernate validation error in the ValidateEventListener method. The suggestion doesn't seem to work for me.
Samuel
+1  A: 

Normally, auto incremented value are ensured to be always increasing, but there can be gaps.

Gaps can happen if two inserts happen concurrently, and one transaction is rolled back, for instance (If the database were to ensure there is no gap, all transactions would need to be serialized.)

EDIT

Example for oracle taken from this page:

CREATE SEQUENCE supplier_seq
    MINVALUE 1
    START WITH 1
    INCREMENT BY 1
    CACHE 20;

With respect to a sequence, the cache option specifies how many sequence values will be stored in memory for faster access.

The downside of creating a sequence with a cache is that if a system failure occurs, all cached sequence values that have not be used, will be "lost". This results in a "gap" in the assigned sequence values. When the system comes back up, Oracle will cache new numbers from where it left off in the sequence, ignoring the so called "lost" sequence values.

ewernli
I'm not familiar with Oracle. What happens if you don't create a cache?
James McMahon
This page discusses sequence with cache and no cache http://www.arikaplan.com/oracle/ari82599.html. Anyway, it was just to point out that some stuff are out of hibernate's hands and are at the database level and can then be database specific, unless you have full control over the way the number are generated and used at the applicative level.
ewernli