views:

33

answers:

1

I've just noticed that for my entity's id, eclipselink assigns an id 1 + the previously greated assigned IN THE SAME SESSION (1), as opposed to in the element table (2). This goes against my application expectations.

What's the easiest way to tell it to do 2?

@Id
@GeneratedValue(strategy = GenerationType.AUTO)
private int objId;

And here is what I have in the database:

ij> connect 'jdbc:derby:db';
ij> set schema memo;
0 Zeilen eingef?gt/aktualisiert/gel?scht
ij> select * from meaning;
OBJID      |LASTPUBLI&|USR_EMAIL                                                                                                                       
-------------------------------------------------------------------------------------------------------------------------------------------------------
1          |NULL      |NULL                                                                                                                            
2          |2010-10-27|NULL                                                                                                                            
51         |NULL      |NULL                                                                                                                            
101        |NULL      |NULL                                                                                      
+1  A: 

When using a GenerationType.AUTO strategy with Derby, EclipseLink defaults to a table generator strategy.

Then, when generating an Id is required, EL will preallocate ids according to the allocationSize (which is 50 by default). To do so, it will first update the column that stores the last value generated to increment it by the allocationSize:

UPDATE SEQUENCE SET SEQ_COUNT = SEQ_COUNT + ? WHERE SEQ_NAME = ?
    bind => [50, SEQ_GEN]

And will then read the new value:

SELECT SEQ_COUNT FROM SEQUENCE WHERE SEQ_NAME = ?
    bind => [SEQ_GEN]

Once done, EL preallocates a pool of ids using the current value - allocationSize + 1 as "first" and value as "last":

local sequencing preallocation for SEQ_GEN: objects: 50 , first: 1, last: 50

And will serve ids from memory until it reaches the last value and will restart a cycle.

Now, if you restart the JVM, there is just no other safe way for EL than preallocating a new pool of ids, "loosing" those from the "previous" range that haven't been used (think multi-JVMs etc), which explains the "jump" from 2 to 51 in your example.

If you want to avoid this, my suggestion would be to switch to an IDENTITY strategy which is supported by Derby (I don't think that configuring the table generator to use an allocationSize of 1 would be a good idea).


I don't think that configuring the table generator to use an allocationSize of 1 would be a good idea. Why not?

Because of the performance hit if you have to read from the "sequence" table for each insert. But on the other hand, 1) this might not be a concern in your case 2) That's the only strategy that allows to get truly sequential ids.

If you're interested, you should be able to configure this globally using the table-generator element in the XML descriptor.

EL highly discourages identity strategy, besides it seems there are mines (because you must wait to commit before reading the value, something I might be doing somewhere).

Well, I can't confirm for EL (I won't test this right now) but Hibernate performs an immediate insert on persist when you use an IDENTITY strategy. I thought EL would behave in the same way. But I might be wrong, this doesn't seem mandated by the spec.

References

Pascal Thivent
I don't think that configuring the table generator to use an allocationSize of 1 would be a good idea. Why not? EL highly discourages identity strategy, besides it seems there are mines (because you must wait to commmit before reading the value, something I might be doing somewhere).
simpatico
@simpatico: See my update.
Pascal Thivent