mirror of
https://github.com/ebean-orm/ebean.git
synced 2024-04-21 10:51:47 +00:00
Feature/cache improvements 2 (#1067)
* New Mode to control queryCache behavior * Collections form the cache have to be read only * findCount not queried in query cache * return modifiable collections from the cache * FIX: Compile errors * No effective code change: reformat code / javadoc
This commit is contained in:
committed by
Rob Bygrave
parent
b8e1dffca2
commit
a6e4e181bf
+111
-17
@@ -1,6 +1,7 @@
|
||||
package org.tests.cache;
|
||||
|
||||
import io.ebean.BaseTestCase;
|
||||
import io.ebean.CacheMode;
|
||||
import io.ebean.Ebean;
|
||||
import io.ebean.bean.BeanCollection;
|
||||
import io.ebean.cache.ServerCache;
|
||||
@@ -105,13 +106,13 @@ public class TestQueryCache extends BaseTestCase {
|
||||
LoggedSqlCollector.start();
|
||||
|
||||
int count0 = Ebean.find(EColAB.class)
|
||||
.setUseQueryCache(true)
|
||||
.setUseQueryCache(CacheMode.ON)
|
||||
.where()
|
||||
.eq("columnB", "count")
|
||||
.findCount();
|
||||
|
||||
int count1 = Ebean.find(EColAB.class)
|
||||
.setUseQueryCache(true)
|
||||
.setUseQueryCache(CacheMode.ON)
|
||||
.where()
|
||||
.eq("columnB", "count")
|
||||
.findCount();
|
||||
@@ -124,7 +125,7 @@ public class TestQueryCache extends BaseTestCase {
|
||||
// and now, ensure that we hit the database
|
||||
LoggedSqlCollector.start();
|
||||
int count2 = Ebean.find(EColAB.class)
|
||||
.setUseQueryCache(false)
|
||||
.setUseQueryCache(CacheMode.OFF)
|
||||
.where()
|
||||
.eq("columnB", "count")
|
||||
.findCount();
|
||||
@@ -140,13 +141,13 @@ public class TestQueryCache extends BaseTestCase {
|
||||
LoggedSqlCollector.start();
|
||||
|
||||
int count0 = Ebean.find(EColAB.class)
|
||||
.setUseQueryCache(true)
|
||||
.setUseQueryCache(CacheMode.ON)
|
||||
.where()
|
||||
.eq("columnB", "abc")
|
||||
.findCount();
|
||||
|
||||
int count1 = Ebean.find(EColAB.class)
|
||||
.setUseQueryCache(true)
|
||||
.setUseQueryCache(CacheMode.ON)
|
||||
.where()
|
||||
.eq("columnB", "def")
|
||||
.findCount();
|
||||
@@ -157,6 +158,58 @@ public class TestQueryCache extends BaseTestCase {
|
||||
assertThat(sql).hasSize(2); // different queries
|
||||
|
||||
}
|
||||
|
||||
@Test
|
||||
public void findCountFirstOnThenRecache() {
|
||||
|
||||
|
||||
LoggedSqlCollector.start();
|
||||
|
||||
int count0 = Ebean.find(EColAB.class)
|
||||
.setUseQueryCache(CacheMode.ON)
|
||||
.where()
|
||||
.eq("columnB", "uvw")
|
||||
.findCount();
|
||||
|
||||
int count1 = Ebean.find(EColAB.class)
|
||||
.setUseQueryCache(CacheMode.RECACHE)
|
||||
.where()
|
||||
.eq("columnB", "uvw")
|
||||
.findCount();
|
||||
|
||||
List<String> sql = LoggedSqlCollector.stop();
|
||||
|
||||
assertThat(count0).isEqualTo(count1);
|
||||
assertThat(sql).hasSize(2); // try recache as second query - it must fetch it
|
||||
|
||||
}
|
||||
|
||||
|
||||
@Test
|
||||
public void findCountFirstRecacheThenOn() {
|
||||
|
||||
|
||||
LoggedSqlCollector.start();
|
||||
|
||||
int count0 = Ebean.find(EColAB.class)
|
||||
.setUseQueryCache(CacheMode.RECACHE)
|
||||
.where()
|
||||
.eq("columnB", "xyz")
|
||||
.findCount();
|
||||
|
||||
int count1 = Ebean.find(EColAB.class)
|
||||
.setUseQueryCache(CacheMode.ON)
|
||||
.where()
|
||||
.eq("columnB", "xyz")
|
||||
.findCount();
|
||||
|
||||
List<String> sql = LoggedSqlCollector.stop();
|
||||
|
||||
assertThat(count0).isEqualTo(count1);
|
||||
assertThat(sql).hasSize(1); // try recache as first query - second "ON" query must fetch it.
|
||||
|
||||
}
|
||||
|
||||
@Test
|
||||
@SuppressWarnings("unchecked")
|
||||
public void test() {
|
||||
@@ -170,7 +223,7 @@ public class TestQueryCache extends BaseTestCase {
|
||||
.ilike("name", "Rob").findList();
|
||||
|
||||
BeanCollection<Customer> bc = (BeanCollection<Customer>) list;
|
||||
Assert.assertFalse(bc.isReadOnly());
|
||||
Assert.assertTrue(bc.isReadOnly());
|
||||
Assert.assertFalse(bc.isEmpty());
|
||||
Assert.assertTrue(!list.isEmpty());
|
||||
Assert.assertTrue(Ebean.getBeanState(list.get(0)).isReadOnly());
|
||||
@@ -188,19 +241,60 @@ public class TestQueryCache extends BaseTestCase {
|
||||
Assert.assertSame(list, list2B);
|
||||
|
||||
|
||||
// TODO: At this stage setReadOnly(false) does not
|
||||
// create a shallow copy of the List/Set/Map
|
||||
|
||||
|
||||
// List<Customer> list3 = Ebean.find(Customer.class).setUseQueryCache(true).setReadOnly(false).where()
|
||||
// .ilike("name", "Rob").findList();
|
||||
//
|
||||
// Assert.assertNotSame(list, list3);
|
||||
// BeanCollection<Customer> bc3 = (BeanCollection<Customer>) list3;
|
||||
// Assert.assertFalse(bc3.isReadOnly());
|
||||
// Assert.assertFalse(bc3.isEmpty());
|
||||
// Assert.assertTrue(list3.size() > 0);
|
||||
// Assert.assertFalse(Ebean.getBeanState(list3.get(0)).isReadOnly());
|
||||
List<Customer> list3 = Ebean.find(Customer.class).setUseQueryCache(true).setReadOnly(false).where()
|
||||
.ilike("name", "Rob").findList();
|
||||
|
||||
Assert.assertNotSame(list, list3);
|
||||
BeanCollection<Customer> bc3 = (BeanCollection<Customer>) list3;
|
||||
Assert.assertFalse(bc3.isReadOnly());
|
||||
Assert.assertFalse(bc3.isEmpty());
|
||||
Assert.assertTrue(list3.size() > 0);
|
||||
// TODO: At this stage setReadOnly(false) does create a shallow copy of the List/Set/Map, but does not
|
||||
// change the read only state in the entities.
|
||||
// Assert.assertFalse(Ebean.getBeanState(list3.get(0)).isReadOnly());
|
||||
|
||||
}
|
||||
|
||||
@Test
|
||||
public void findIds() {
|
||||
|
||||
new EColAB("03", "someId").save();
|
||||
new EColAB("04", "someId").save();
|
||||
new EColAB("05", "someId").save();
|
||||
|
||||
|
||||
LoggedSqlCollector.start();
|
||||
|
||||
List<Integer> colA_first = Ebean.find(EColAB.class)
|
||||
.setUseQueryCache(CacheMode.ON)
|
||||
.where()
|
||||
.eq("columnB", "someId")
|
||||
.findIds();
|
||||
|
||||
List<Integer> colA_second = Ebean.find(EColAB.class)
|
||||
.setUseQueryCache(CacheMode.ON)
|
||||
.where()
|
||||
.eq("columnB", "someId")
|
||||
.findIds();
|
||||
|
||||
List<String> sql = LoggedSqlCollector.stop();
|
||||
|
||||
assertThat(colA_first).isSameAs(colA_second);
|
||||
assertThat(colA_first).hasSize(3);
|
||||
assertThat(sql).hasSize(1);
|
||||
|
||||
// and now, ensure that we hit the database
|
||||
LoggedSqlCollector.start();
|
||||
colA_second = Ebean.find(EColAB.class)
|
||||
.setUseQueryCache(CacheMode.RECACHE)
|
||||
.where()
|
||||
.eq("columnB", "someId")
|
||||
.findIds();
|
||||
sql = LoggedSqlCollector.stop();
|
||||
|
||||
assertThat(sql).hasSize(1);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@@ -0,0 +1,111 @@
|
||||
package org.tests.cache;
|
||||
|
||||
import io.ebean.BaseTestCase;
|
||||
import io.ebean.CacheMode;
|
||||
import io.ebean.Ebean;
|
||||
import io.ebean.EbeanServer;
|
||||
import io.ebean.Query;
|
||||
|
||||
import org.tests.model.basic.EBasicVer;
|
||||
import org.junit.Test;
|
||||
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
import java.util.Set;
|
||||
|
||||
import static org.assertj.core.api.Assertions.*;
|
||||
|
||||
public class TestQueryCacheReadOnly extends BaseTestCase {
|
||||
|
||||
@Test
|
||||
public void testReadOnly() {
|
||||
|
||||
EbeanServer server = Ebean.getServer(null);
|
||||
EBasicVer account = new EBasicVer("an other junk");
|
||||
server.save(account);
|
||||
|
||||
Query<EBasicVer> baseQuery = server.find(EBasicVer.class).setUseQueryCache(CacheMode.ON);
|
||||
|
||||
List<EBasicVer> alist = baseQuery.findList();
|
||||
assertThat(alist).isNotEmpty();
|
||||
assertThatThrownBy(alist::clear).hasMessageContaining("This collection is in ReadOnly mode");
|
||||
alist = baseQuery.findList();
|
||||
assertThat(alist).isNotEmpty();
|
||||
assertThatThrownBy(alist::clear).hasMessageContaining("This collection is in ReadOnly mode");
|
||||
|
||||
Map<String,EBasicVer> amap = baseQuery.setMapKey("name").findMap();
|
||||
assertThat(amap).isNotEmpty();
|
||||
assertThatThrownBy(amap::clear).hasMessageContaining("This collection is in ReadOnly mode");
|
||||
amap = baseQuery.setMapKey("name").findMap();
|
||||
assertThat(amap).isNotEmpty();
|
||||
assertThatThrownBy(amap::clear).hasMessageContaining("This collection is in ReadOnly mode");
|
||||
|
||||
Set<EBasicVer> aset = baseQuery.findSet();
|
||||
assertThat(aset).isNotEmpty();
|
||||
assertThatThrownBy(aset::clear).hasMessageContaining("This collection is in ReadOnly mode");
|
||||
aset = baseQuery.findSet();
|
||||
assertThat(aset).isNotEmpty();
|
||||
assertThatThrownBy(aset::clear).hasMessageContaining("This collection is in ReadOnly mode");
|
||||
|
||||
// we will get an unmodifiable collection here
|
||||
List<Object> attributeList = baseQuery.select("name").findSingleAttributeList();
|
||||
assertThat(attributeList).isNotEmpty();
|
||||
assertThatThrownBy(attributeList::clear).isInstanceOf(UnsupportedOperationException.class);
|
||||
attributeList = baseQuery.select("name").findSingleAttributeList();
|
||||
assertThat(attributeList).isNotEmpty();
|
||||
assertThatThrownBy(attributeList::clear).isInstanceOf(UnsupportedOperationException.class);
|
||||
|
||||
List<Object> idList = baseQuery.select("name").findIds();
|
||||
assertThat(idList).isNotEmpty();
|
||||
assertThatThrownBy(idList::clear).isInstanceOf(UnsupportedOperationException.class);
|
||||
idList = baseQuery.select("name").findIds();
|
||||
assertThat(idList).isNotEmpty();
|
||||
assertThatThrownBy(idList::clear).isInstanceOf(UnsupportedOperationException.class);
|
||||
}
|
||||
|
||||
|
||||
@Test
|
||||
public void testNotReadOnly() {
|
||||
|
||||
EbeanServer server = Ebean.getServer(null);
|
||||
EBasicVer account = new EBasicVer("an other junk");
|
||||
server.save(account);
|
||||
|
||||
Query<EBasicVer> baseQuery = server.find(EBasicVer.class).setUseQueryCache(CacheMode.ON).setReadOnly(false);
|
||||
|
||||
List<EBasicVer> alist = baseQuery.findList();
|
||||
assertThat(alist).isNotEmpty();
|
||||
alist.clear();
|
||||
alist = baseQuery.findList();
|
||||
assertThat(alist).isNotEmpty();
|
||||
alist.clear();
|
||||
|
||||
Map<String,EBasicVer> amap = baseQuery.setMapKey("name").findMap();
|
||||
assertThat(amap).isNotEmpty();
|
||||
amap.clear();
|
||||
amap = baseQuery.setMapKey("name").findMap();
|
||||
assertThat(amap).isNotEmpty();
|
||||
amap.clear();
|
||||
|
||||
Set<EBasicVer> aset = baseQuery.findSet();
|
||||
assertThat(aset).isNotEmpty();
|
||||
aset.clear();
|
||||
aset = baseQuery.findSet();
|
||||
assertThat(aset).isNotEmpty();
|
||||
aset.clear();
|
||||
|
||||
List<Object> attributeList = baseQuery.select("name").findSingleAttributeList();
|
||||
assertThat(attributeList).isNotEmpty();
|
||||
attributeList.clear();
|
||||
attributeList = baseQuery.select("name").findSingleAttributeList();
|
||||
assertThat(attributeList).isNotEmpty();
|
||||
attributeList.clear();
|
||||
|
||||
List<Object> idList = baseQuery.select("name").findIds();
|
||||
assertThat(idList).isNotEmpty();
|
||||
idList.clear();
|
||||
idList = baseQuery.select("name").findIds();
|
||||
assertThat(idList).isNotEmpty();
|
||||
idList.clear();
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user