diff --git a/ebean-core/src/main/java/io/ebeaninternal/server/core/PersistRequestBean.java b/ebean-core/src/main/java/io/ebeaninternal/server/core/PersistRequestBean.java index 81eef4eb0..dc14a15ae 100644 --- a/ebean-core/src/main/java/io/ebeaninternal/server/core/PersistRequestBean.java +++ b/ebean-core/src/main/java/io/ebeaninternal/server/core/PersistRequestBean.java @@ -291,6 +291,13 @@ public final class PersistRequestBean extends PersistRequest implements BeanP } } + private void onFailedUpdateUndoGeneratedProperties() { + for (BeanProperty prop : beanDescriptor.propertiesGenUpdate()) { + Object oldVal = intercept.getOrigValue(prop.propertyIndex()); + prop.setValue(entityBean, oldVal); + } + } + private void onInsertGeneratedProperties() { for (BeanProperty prop : beanDescriptor.propertiesGenInsert()) { Object value = prop.generatedProperty().getInsertValue(prop, entityBean, now()); @@ -807,6 +814,7 @@ public final class PersistRequestBean extends PersistRequest implements BeanP public void checkRowCount(int rowCount) { if (rowCount != 1 && rowCount != Statement.SUCCESS_NO_INFO) { if (ConcurrencyMode.VERSION == concurrencyMode) { + onFailedUpdateUndoGeneratedProperties(); throw new OptimisticLockException("Data has changed. updated row count " + rowCount, null, bean); } else if (rowCount == 0 && type == Type.UPDATE) { throw new EntityNotFoundException("No rows updated"); diff --git a/ebean-test/src/test/java/org/tests/basic/TestIUDVanilla.java b/ebean-test/src/test/java/org/tests/basic/TestIUDVanilla.java index bdc902609..f69f38669 100644 --- a/ebean-test/src/test/java/org/tests/basic/TestIUDVanilla.java +++ b/ebean-test/src/test/java/org/tests/basic/TestIUDVanilla.java @@ -9,7 +9,10 @@ import org.tests.model.basic.UTMaster; import javax.persistence.OptimisticLockException; import java.sql.Timestamp; -import static org.junit.jupiter.api.Assertions.*; +import static org.assertj.core.api.Assertions.assertThat; +import static org.junit.jupiter.api.Assertions.assertNotNull; +import static org.junit.jupiter.api.Assertions.assertNotSame; +import static org.junit.jupiter.api.Assertions.assertThrows; public class TestIUDVanilla extends BaseTestCase { @@ -79,4 +82,27 @@ public class TestIUDVanilla extends BaseTestCase { e0.setVersion(42); assertThrows(OptimisticLockException.class, () -> e0.update()); } + + @Test + public void testOptimisticLockException() { + UTMaster e0 = new UTMaster("optLock"); + DB.save(e0); + + e0 = DB.find(UTMaster.class).where().eq("name", "optLock").findOne(); + UTMaster e1 = DB.find(UTMaster.class).where().eq("name", "optLock").findOne(); + + int oldVersion = e0.getVersion(); + e0.setDescription("foo"); + e0.save(); + assertThat(e0.getVersion()).isGreaterThan(oldVersion); + + e1.setDescription("bar"); + oldVersion = e1.getVersion(); + assertThrows(OptimisticLockException.class, e1::save); + // after optimisticLockExecption, a restore of version is expected + assertThat(e1.getVersion()).isEqualTo(oldVersion); + // and subsequent saves must fail + assertThrows(OptimisticLockException.class, e1::save); + } + }