java hibernate jpa concurrency hashmap

java - ConcurrentModificationException y un HashMap



hibernate jpa (5)

Estoy usando objetos persistentes usando JPA. El objeto principal tiene una relación One-Many propietaria con otro objeto. El otro objeto se almacena en un HashMap. ¿Qué tipo de sincronización solucionaría este problema? Parece suceder en momentos completamente aleatorios y es muy impredecible. Aquí está la excepción que recibo:

Exception in thread "pool-1-thread-1" java.util.ConcurrentModificationException at java.util.HashMap$HashIterator.nextEntry(Unknown Source) at java.util.HashMap$ValueIterator.next(Unknown Source) at org.hibernate.collection.AbstractPersistentCollection$IteratorProxy.next(AbstractPersistentCollection.java:555) at org.hibernate.engine.Cascade.cascadeCollectionElements(Cascade.java:296) at org.hibernate.engine.Cascade.cascadeCollection(Cascade.java:242) at org.hibernate.engine.Cascade.cascadeAssociation(Cascade.java:219) at org.hibernate.engine.Cascade.cascadeProperty(Cascade.java:169) at org.hibernate.engine.Cascade.cascade(Cascade.java:130)


Esto no es un problema de sincronización. Esto ocurrirá si la colección subyacente que se está iterando es modificada por cualquier cosa que no sea el iterador mismo.

Iterator it = map.entrySet().iterator(); while (it.hasNext()) { Entry item = it.next(); map.remove(item.getKey()); }

Esto lanzará una ConcurrentModificationException cuando se llame a it.hasNext () por segunda vez.

El enfoque correcto sería

Iterator it = map.entrySet().iterator(); while (it.hasNext()) { Entry item = it.next(); it.remove(); }

Suponiendo que este iterador sea compatible con la operación remove ().


Intente utilizar un ConcurrentHashMap en lugar de un HashMap simple


Pruebe CopyOnWriteArrayList o CopyOnWriteArraySet dependiendo de lo que intente hacer.


Quizás otra solución sería adquirir un bloqueo antes de comenzar su modificación / persistencia para no tener otro hilo que modifique lo que está iterando

private ReadWriteLock lock = new ReentrantReadWriteLock(); lock.writeLock().lock(); try{ //itterate and persist } finally{ lock.writeLock().unlock(); }

  • Si no está haciendo ninguna manipulación, lock.readLock (). Lock () también está bien

Suena menos como un problema de sincronización de Java y más como un problema de bloqueo de la base de datos.

No sé si la adición de una versión a todas las clases persistentes lo resolverá, pero esa es una forma en que Hibernate puede proporcionar acceso exclusivo a las filas de una tabla.

Podría ser que el nivel de aislamiento deba ser más alto. Si permite "lecturas sucias", tal vez necesite subir de nivel para ser serializable.