diff --git a/src/main/java/io/ebeaninternal/api/SpiQuery.java b/src/main/java/io/ebeaninternal/api/SpiQuery.java index 4f7184830..ae8b83805 100644 --- a/src/main/java/io/ebeaninternal/api/SpiQuery.java +++ b/src/main/java/io/ebeaninternal/api/SpiQuery.java @@ -644,9 +644,9 @@ public interface SpiQuery extends Query, TxnProfileEventCodes { boolean isBeanCachePut(); /** - * Return true if the bean cache is being explicitly loaded via RECACHE mode. + * Return true if we must hit the DB (Cache reload or select for update). */ - boolean isBeanCacheReload(); + boolean isForceHitDatabase(); /** * Return the cache mode for using the bean cache (Get and Put). diff --git a/src/main/java/io/ebeaninternal/server/autotune/service/BaseQueryTuner.java b/src/main/java/io/ebeaninternal/server/autotune/service/BaseQueryTuner.java index 1014219e6..1c4d82e66 100644 --- a/src/main/java/io/ebeaninternal/server/autotune/service/BaseQueryTuner.java +++ b/src/main/java/io/ebeaninternal/server/autotune/service/BaseQueryTuner.java @@ -144,7 +144,7 @@ public class BaseQueryTuner { default: // not using autoTune when explicitly loading the l2 bean cache // or when using Versions query - return !query.isBeanCacheReload() && SpiQuery.TemporalMode.VERSIONS != query.getTemporalMode(); + return !query.isForceHitDatabase() && SpiQuery.TemporalMode.VERSIONS != query.getTemporalMode(); } } diff --git a/src/main/java/io/ebeaninternal/server/core/DefaultServer.java b/src/main/java/io/ebeaninternal/server/core/DefaultServer.java index c63638240..2e2d2082c 100644 --- a/src/main/java/io/ebeaninternal/server/core/DefaultServer.java +++ b/src/main/java/io/ebeaninternal/server/core/DefaultServer.java @@ -1166,7 +1166,7 @@ public final class DefaultServer implements SpiServer, SpiEbeanServer { SpiQuery spiQuery = (SpiQuery) query; spiQuery.setType(Type.BEAN); - if (SpiQuery.Mode.NORMAL == spiQuery.getMode() && !spiQuery.isBeanCacheReload()) { + if (SpiQuery.Mode.NORMAL == spiQuery.getMode() && !spiQuery.isForceHitDatabase()) { // See if we can skip doing the fetch completely by getting the bean from the // persistence context or the bean cache T bean = findIdCheckPersistenceContextAndCache(t, spiQuery, spiQuery.getId()); diff --git a/src/main/java/io/ebeaninternal/server/querydefn/DefaultOrmQuery.java b/src/main/java/io/ebeaninternal/server/querydefn/DefaultOrmQuery.java index 50683c1dc..be5b769c5 100644 --- a/src/main/java/io/ebeaninternal/server/querydefn/DefaultOrmQuery.java +++ b/src/main/java/io/ebeaninternal/server/querydefn/DefaultOrmQuery.java @@ -1276,8 +1276,8 @@ public class DefaultOrmQuery implements SpiQuery { } @Override - public boolean isBeanCacheReload() { - return CacheMode.PUT == useBeanCache; + public boolean isForceHitDatabase() { + return forUpdate != null || CacheMode.PUT == useBeanCache; } @Override diff --git a/src/test/java/org/tests/basic/TestQueryForUpdate.java b/src/test/java/org/tests/basic/TestQueryForUpdate.java index c72884b89..54f339ffc 100644 --- a/src/test/java/org/tests/basic/TestQueryForUpdate.java +++ b/src/test/java/org/tests/basic/TestQueryForUpdate.java @@ -8,8 +8,10 @@ import io.ebean.Query; import io.ebean.Transaction; import io.ebean.annotation.ForPlatform; import io.ebean.annotation.Platform; +import org.ebeantest.LoggedSqlCollector; import org.junit.Test; import org.tests.model.basic.Customer; +import org.tests.model.basic.EBasic; import org.tests.model.basic.ResetBasicData; import java.util.List; @@ -40,6 +42,42 @@ public class TestQueryForUpdate extends BaseTestCase { } } + @Test + @ForPlatform({ + Platform.H2, Platform.ORACLE, Platform.POSTGRES, Platform.SQLSERVER, Platform.MYSQL + }) + public void testForUpdate_when_alreadyInPC() { + + EBasic basic = new EBasic("test PC cache"); + Ebean.save(basic); + + try (Transaction transaction = Ebean.beginTransaction()) { + + LoggedSqlCollector.start(); + + EBasic basic0 = Ebean.find(EBasic.class, basic.getId()); + assertThat(basic0).isNotNull(); + + EBasic basic1 = Ebean.find(EBasic.class) + .setId( basic.getId()) + .forUpdate() + .findOne(); + + assertThat(basic1).isNotNull(); + assertThat(basic1).isSameAs(basic0); + + List sql = LoggedSqlCollector.stop(); + assertThat(sql).hasSize(2); + if (isH2() || isPostgres()) { + assertThat(sql.get(0)).contains("from e_basic t0 where t0.id ="); + assertThat(sql.get(1)).contains("from e_basic t0 where t0.id ="); + assertThat(sql.get(1)).contains("for update"); + } + + transaction.end(); + } + } + @Test @ForPlatform({ Platform.H2, Platform.POSTGRES, Platform.SQLSERVER, Platform.ORACLE