I am in the midst of changing my JPA code around to make use of threads. I have a separate entity manager and transaction for each thread.
What I used to have (for the single threaded environment) was code like:
// get object from the entity manager
X x = getObjectX(jpaQuery);
if(x == null)
{
x = new X();
x.setVariable(foo);
entityManager.persist(x);
}
With that code in the multi threaded environment I am getting duplicate keys since, I assume, getObjectX returns null for a thread, then that thread is swapped out, the next thread calls getObjextX, also getting null, and then both threads will create and persist a new X().
Short of adding in synchronization, is there an atomic way to get/save-if-doesn't-exist a value with JPA or should I rethink my approach
EDIT:
I am using the latest Eclipselink and MySql 5.1
EDIT 2:
I added synchronization... MASSIVE performance hit (to the point that it cannot be used). Going to gather all of the data up back on the main thread and then do the creations on that thread.
Short sad answer is no the JPA API cannot do that for you. The whole API is more or less built around the optimistic principle of assuming things are going to work and throwing exceptions in the event of concurrent modification.
If this is happening often, there's likely some other component (whatever generates foo?) that could benefit from being made threadsafe, as perhaps an alternative to synchronizing around the query+create.
Some "hack" to consider:
hashCode()
and equals()
based on the business key of the objects (not the generated id)synchronize on:
(obj.getClass().getName() + String.valueOf(hashCode())).intern()
Thus you will get locks only in the relevant cases.
I think you will need to add a unique constraint on the fields that are used in "jpaQuery" so that the database can not create duplicate rows with the same criteria used in the contraints for that query. The calling code will need to trap the resulting exception that occurs as a result of the constraint violation (ideally it will be an EntityExistsException, but the spec is not clear on this case).
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With