Hi, I'm using Hibernate 4.0.1 via JPA2 and have an Entity (portfolio) with a collection of entries as follows:
Code:
@ElementCollection (fetch = FetchType.EAGER)
@CollectionTable (name = "portfolio_entry", joinColumns = @JoinColumn (name = "portfolio_id"))
private final Map<String, Position> positions =
new ConcurrentHashMap<String, Position>();
I understand that when this entity is created by Hibernate, the map instance is actually a PersistentMap, and not a ConcurrentHashMap. As such, it doesn't support modification while it is being persisted (throws a ConcurrentModificationException as I believe it uses a java.util.HashMap underyling)
Is there any way to have Hibernate use a concurrent modification safe map as the underlying? My application makes rapid changes to the collection on the main application thread, while performing persistence of the entity on a background thread. Given the time taken to persist (merge actually), there are sometime new changes during persistence, which is the issue. I don't have an issue with the persistence lagging behind the live object since the persist operations are queued.
One option is to copy the collection on the background thread and persist the copy. That would work okay, but I'm just wondering if there's a more efficient solution. I'm very much a Hibernate/JPA novice so any advice would be appreciated. In case it's relevant, the entity is always detached after merge.
One thing I tried was:
- fetch the entity from the DB
- construct a new entity object explicitly (i.e. new) so that the map instance is a ConcurrentHashMap
- copy the data from the DB object to the manually created Entity
- use that object in the app and persist it
This led to a different ConcurrentModificationException, this time during commit rather than merge:
Code:
Caused by: java.util.ConcurrentModificationException
at java.util.LinkedHashMap$LinkedHashIterator.nextEntry(LinkedHashMap.java:373)
at java.util.LinkedHashMap$EntryIterator.next(LinkedHashMap.java:392)
at java.util.LinkedHashMap$EntryIterator.next(LinkedHashMap.java:391)
at org.hibernate.internal.util.collections.IdentityMap.entryArray(IdentityMap.java:164)
at org.hibernate.internal.util.collections.IdentityMap.concurrentEntries(IdentityMap.java:76)
at org.hibernate.event.internal.AbstractFlushingEventListener.prepareEntityFlushes(AbstractFlushingEventListener.java:147)
at org.hibernate.event.internal.AbstractFlushingEventListener.flushEverythingToExecutions(AbstractFlushingEventListener.java:88)
at org.hibernate.event.internal.DefaultFlushEventListener.onFlush(DefaultFlushEventListener.java:51)
Thanks