2

The following (simplified version of our) code passes our JUnit tests under Hibernate, but not under EclipseLink. What is needed to make this work under EclipseLink?

public static void store(EntityManager em, String a, String b) {
    Entry entry=new Entry();
    entry.setFirst(a);
    entry.setLast(b);
    em.persist(entry);
    em.persist(new SubEntry(entry.getId(), a, b));
}

It fails because entry.getId() is returning 0 when using EclipseLink. What is the appropriate way to retrieve the unique identifier of an object that has just been stored?

It appears obvious that the above code doesn't make sense, as doing an entry.getId() before the transaction has been committed probably does not make sense, however hibernate allowed it.

1 Answers1

2

There are a few things going on here. Unless you provide some of the code for your entity classes, we can't know what kind of strategy you are using for primary key generation. Let me assume that you're using a strategy that allows the database to generate a primary key for your Entry class, such as a sequence or auto-number column. Let me further assume that you're calling this method inside an active transaction. If you insert a call to em.flush() right after your call to em.persist(entry) then I think this will work, given the assumptions that I stated above.

The unknown that I see is whether or not entry is a reference to a managed entity when you make the second call to em.persist() and whether or not it has been assigned an id (primary key) value yet.

Jim Tough
  • 14,843
  • 23
  • 75
  • 96
  • Your assumptions are correct. Thanks for the pointers, you have confirmed there is no simple answer! It is a bit of an interesting gotchya that eclipselink and hibernate have inconsistent implementations of the JPA specification. It seems em.flush() is the answer. We are now worried how many other places in the code we are going to have this problem!! – James Brown Nov 22 '10 at 00:49
  • I would vote your answer up but it seems I am not allowed to because I am new. Sorry. – James Brown Nov 22 '10 at 00:50
  • 1
    I think the default "flush" mode is AUTO, which allows the provider to flush pending changes to the database whenever it wants to and would vary from one provider to another. – Jim Tough Nov 22 '10 at 00:55
  • 1
    Also, it is only for IDENTITY sequencing that the value will not be present until the em.flush. – Gordon Yorke Nov 22 '10 at 13:37