From 35bff7c3e7493081d2e88db4fbdf51dae0c296cc Mon Sep 17 00:00:00 2001 From: Roland Praml Date: Mon, 9 Aug 2021 13:48:22 +0200 Subject: [PATCH 1/3] FIX: Cache exist query results --- .../server/core/PersistRequestBean.java | 8 ++++++ .../java/org/tests/basic/TestIUDVanilla.java | 25 +++++++++++++++++++ 2 files changed, 33 insertions(+) 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 8b3285c7a..07aac16bb 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 @@ -339,6 +339,13 @@ public final class PersistRequestBean extends PersistRequest implements BeanP } } + private void onFailedUpdateUndoGeneratedProperties() { + for (BeanProperty prop : beanDescriptor.propertiesGenUpdate()) { + Object oldVal = intercept.getOrigValue(prop.getPropertyIndex()); + prop.setValue(entityBean, oldVal); + } + } + private void onInsertGeneratedProperties() { for (BeanProperty prop : beanDescriptor.propertiesGenInsert()) { Object value = prop.getGeneratedProperty().getInsertValue(prop, entityBean, now()); @@ -857,6 +864,7 @@ public final class PersistRequestBean extends PersistRequest implements BeanP public final 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-core/src/test/java/org/tests/basic/TestIUDVanilla.java b/ebean-core/src/test/java/org/tests/basic/TestIUDVanilla.java index 6a88595ef..82170e4a3 100644 --- a/ebean-core/src/test/java/org/tests/basic/TestIUDVanilla.java +++ b/ebean-core/src/test/java/org/tests/basic/TestIUDVanilla.java @@ -10,6 +10,9 @@ import org.tests.model.basic.UTMaster; import javax.persistence.OptimisticLockException; import java.sql.Timestamp; +import static org.assertj.core.api.Assertions.assertThat; +import static org.assertj.core.api.Assertions.assertThatThrownBy; + public class TestIUDVanilla extends BaseTestCase { @Test @@ -79,4 +82,26 @@ public class TestIUDVanilla extends BaseTestCase { e0.setVersion(42); 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(); + assertThatThrownBy(e1::save).isInstanceOf(OptimisticLockException.class); + // after optimisticLockExecption, a restore of version is expected + assertThat(e1.getVersion()).isEqualTo(oldVersion); + // and subsequent saves must fail + assertThatThrownBy(e1::save).isInstanceOf(OptimisticLockException.class); + } } From a582db910185521b6dfb2e8eeead4a57b3f7aafd Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jonas=20P=C3=B6hler?= Date: Mon, 13 Sep 2021 17:04:22 +0200 Subject: [PATCH 2/3] Re-add test and fix compile error --- .../server/core/PersistRequestBean.java | 2 +- .../java/org/tests/basic/TestIUDVanilla.java | 29 ++++++++++++++++++- 2 files changed, 29 insertions(+), 2 deletions(-) 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 fd4f8e555..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 @@ -293,7 +293,7 @@ public final class PersistRequestBean extends PersistRequest implements BeanP private void onFailedUpdateUndoGeneratedProperties() { for (BeanProperty prop : beanDescriptor.propertiesGenUpdate()) { - Object oldVal = intercept.getOrigValue(prop.getPropertyIndex()); + Object oldVal = intercept.getOrigValue(prop.propertyIndex()); prop.setValue(entityBean, oldVal); } } 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..ad7605162 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,11 @@ 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.assertj.core.api.Assertions.assertThatThrownBy; +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 +83,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(); + assertThatThrownBy(e1::save).isInstanceOf(OptimisticLockException.class); + // after optimisticLockExecption, a restore of version is expected + assertThat(e1.getVersion()).isEqualTo(oldVersion); + // and subsequent saves must fail + assertThatThrownBy(e1::save).isInstanceOf(OptimisticLockException.class); + } + } From aea50b4805bf502b8f1485b0adccc3a7fafd4988 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jonas=20P=C3=B6hler?= Date: Wed, 15 Sep 2021 15:30:07 +0200 Subject: [PATCH 3/3] Fix assert methods and import --- ebean-test/src/test/java/org/tests/basic/TestIUDVanilla.java | 5 ++--- 1 file changed, 2 insertions(+), 3 deletions(-) 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 ad7605162..f69f38669 100644 --- a/ebean-test/src/test/java/org/tests/basic/TestIUDVanilla.java +++ b/ebean-test/src/test/java/org/tests/basic/TestIUDVanilla.java @@ -10,7 +10,6 @@ import javax.persistence.OptimisticLockException; import java.sql.Timestamp; import static org.assertj.core.api.Assertions.assertThat; -import static org.assertj.core.api.Assertions.assertThatThrownBy; import static org.junit.jupiter.api.Assertions.assertNotNull; import static org.junit.jupiter.api.Assertions.assertNotSame; import static org.junit.jupiter.api.Assertions.assertThrows; @@ -99,11 +98,11 @@ public class TestIUDVanilla extends BaseTestCase { e1.setDescription("bar"); oldVersion = e1.getVersion(); - assertThatThrownBy(e1::save).isInstanceOf(OptimisticLockException.class); + assertThrows(OptimisticLockException.class, e1::save); // after optimisticLockExecption, a restore of version is expected assertThat(e1.getVersion()).isEqualTo(oldVersion); // and subsequent saves must fail - assertThatThrownBy(e1::save).isInstanceOf(OptimisticLockException.class); + assertThrows(OptimisticLockException.class, e1::save); } }