From 112465ca339d901b247c5174f2c355f23fc3d26c Mon Sep 17 00:00:00 2001 From: Nicki Watt Date: Mon, 9 Dec 2013 23:32:59 +0000 Subject: [PATCH] DATAGRAPH-413: ConcurrentModificationException occurs when trying to persist entity after modification outside of transaction --- ...ModificationOutsideOfTransactionTests.java | 21 +++++++++++++++++++ .../fieldaccess/DetachedEntityState.java | 9 ++++++++ 2 files changed, 30 insertions(+) diff --git a/spring-data-neo4j-aspects/src/test/java/org/springframework/data/neo4j/aspects/support/ModificationOutsideOfTransactionTests.java b/spring-data-neo4j-aspects/src/test/java/org/springframework/data/neo4j/aspects/support/ModificationOutsideOfTransactionTests.java index c8ee7ada2..272dfda2f 100644 --- a/spring-data-neo4j-aspects/src/test/java/org/springframework/data/neo4j/aspects/support/ModificationOutsideOfTransactionTests.java +++ b/spring-data-neo4j-aspects/src/test/java/org/springframework/data/neo4j/aspects/support/ModificationOutsideOfTransactionTests.java @@ -178,6 +178,27 @@ public class ModificationOutsideOfTransactionTests extends EntityTestBase { } } + @Test + public void testSetPropertyOutsideTransactionCanBePersistedThereafter() + { + Person p = persistedPerson( "Michael", 35 ); + p.setAge( 25 ); + assertEquals(25, p.getAge()); + + try (Transaction tx = neo4jTemplate.getGraphDatabase().beginTx()) { + assertEquals( 35, nodeFor( p ).getProperty("age") ); + tx.success(); + } + + p.persist(); + + try (Transaction tx = neo4jTemplate.getGraphDatabase().beginTx()) { + assertEquals( 25, nodeFor( p ).getProperty("age") ); + tx.success(); + } + + } + @Test public void shouldWorkWithUninitializedCollectionFieldWithoutUnderlyingState() { Group group = new Group(); diff --git a/spring-data-neo4j/src/main/java/org/springframework/data/neo4j/fieldaccess/DetachedEntityState.java b/spring-data-neo4j/src/main/java/org/springframework/data/neo4j/fieldaccess/DetachedEntityState.java index b74e5b998..e1d308636 100644 --- a/spring-data-neo4j/src/main/java/org/springframework/data/neo4j/fieldaccess/DetachedEntityState.java +++ b/spring-data-neo4j/src/main/java/org/springframework/data/neo4j/fieldaccess/DetachedEntityState.java @@ -159,6 +159,15 @@ public class DetachedEntityState implements EntityState { Object valueFromDb = null; if (template.transactionIsRunning()) { valueFromDb = unwrap(delegate.getValue(property, MappingPolicy.MAP_FIELD_DIRECT_POLICY)); + } else { + // For Implicit Transactions, we need to create + // a tx to ensure we get the correct previous value + // otherwise the possibility of getting a concurrent + // modification exception when next persisting may occur + try (Transaction tx = template.getGraphDatabaseService().beginTx()) { + valueFromDb = unwrap(delegate.getValue(property, MappingPolicy.MAP_FIELD_DIRECT_POLICY)); + tx.success(); + } } addDirty(property, valueFromDb, true); }