mirror of
https://github.com/ebean-orm/ebean.git
synced 2026-10-23 21:15:52 +00:00
#1401 - FOR UPDATE queries inside a transaction are not honored when beans are already cached (in the persistence context)
This commit is contained in:
@@ -644,9 +644,9 @@ public interface SpiQuery<T> extends Query<T>, 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).
|
||||
|
||||
@@ -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();
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -1166,7 +1166,7 @@ public final class DefaultServer implements SpiServer, SpiEbeanServer {
|
||||
|
||||
SpiQuery<T> spiQuery = (SpiQuery<T>) 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());
|
||||
|
||||
@@ -1276,8 +1276,8 @@ public class DefaultOrmQuery<T> implements SpiQuery<T> {
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean isBeanCacheReload() {
|
||||
return CacheMode.PUT == useBeanCache;
|
||||
public boolean isForceHitDatabase() {
|
||||
return forUpdate != null || CacheMode.PUT == useBeanCache;
|
||||
}
|
||||
|
||||
@Override
|
||||
|
||||
@@ -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<String> 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
|
||||
|
||||
Reference in New Issue
Block a user