diff --git a/ebean-core/src/main/java/io/ebeaninternal/api/SpiQuery.java b/ebean-core/src/main/java/io/ebeaninternal/api/SpiQuery.java index 5a6ae2217..3f2e97893 100644 --- a/ebean-core/src/main/java/io/ebeaninternal/api/SpiQuery.java +++ b/ebean-core/src/main/java/io/ebeaninternal/api/SpiQuery.java @@ -81,6 +81,11 @@ public interface SpiQuery extends Query, SpiQueryFetch, TxnProfileEventCod */ ID_LIST(FIND_ID_LIST, "findIds"), + /** + * Find exists. + */ + EXISTS(FIND_EXISTS, "exists"), + /** * Find single attribute. */ diff --git a/ebean-core/src/main/java/io/ebeaninternal/api/TxnProfileEventCodes.java b/ebean-core/src/main/java/io/ebeaninternal/api/TxnProfileEventCodes.java index 231d38296..c4d1ea0be 100644 --- a/ebean-core/src/main/java/io/ebeaninternal/api/TxnProfileEventCodes.java +++ b/ebean-core/src/main/java/io/ebeaninternal/api/TxnProfileEventCodes.java @@ -26,6 +26,7 @@ public interface TxnProfileEventCodes { String FIND_MANY = "fm"; String FIND_ITERATE = "fe"; String FIND_ID_LIST = "fi"; + String FIND_EXISTS = "ex"; String FIND_ATTRIBUTE = "fa"; String FIND_COUNT = "fc"; String FIND_SUBQUERY = "fs"; diff --git a/ebean-core/src/main/java/io/ebeaninternal/server/core/DefaultServer.java b/ebean-core/src/main/java/io/ebeaninternal/server/core/DefaultServer.java index 1c77e06a8..8dfa8fd29 100644 --- a/ebean-core/src/main/java/io/ebeaninternal/server/core/DefaultServer.java +++ b/ebean-core/src/main/java/io/ebeaninternal/server/core/DefaultServer.java @@ -1291,7 +1291,12 @@ public final class DefaultServer implements SpiServer, SpiEbeanServer { @Override public boolean exists(Query ormQuery, Transaction transaction) { Query ormQueryCopy = ormQuery.copy().setMaxRows(1); - SpiOrmQueryRequest request = createQueryRequest(Type.ID_LIST, ormQueryCopy, transaction); + SpiOrmQueryRequest request = createQueryRequest(Type.EXISTS, ormQueryCopy, transaction); + List ids = request.getFromQueryCache(); + if (ids != null) { + return !ids.isEmpty(); + } + try { request.initTransIfRequired(); return !request.findIds().isEmpty(); diff --git a/ebean-core/src/test/java/org/tests/cache/TestQueryCache.java b/ebean-core/src/test/java/org/tests/cache/TestQueryCache.java index 4c4d56109..a2e65e00c 100644 --- a/ebean-core/src/test/java/org/tests/cache/TestQueryCache.java +++ b/ebean-core/src/test/java/org/tests/cache/TestQueryCache.java @@ -3,6 +3,7 @@ package org.tests.cache; import io.ebean.BaseTestCase; import io.ebean.CacheMode; import io.ebean.DB; +import io.ebean.Ebean; import io.ebean.ExpressionList; import io.ebean.bean.BeanCollection; import io.ebean.cache.ServerCache; @@ -135,6 +136,43 @@ public class TestQueryCache extends BaseTestCase { assertThat(sql).hasSize(1); } + @Test + public void exists() { + + new EColAB("06", "exists").save(); + new EColAB("07", "exists").save(); + + LoggedSqlCollector.start(); + + boolean exists0 = Ebean.find(EColAB.class) + .setUseQueryCache(CacheMode.ON) + .where() + .eq("columnB", "exists") + .exists(); + + boolean exists1 = Ebean.find(EColAB.class) + .setUseQueryCache(CacheMode.ON) + .where() + .eq("columnB", "exists") + .exists(); + + List sql = LoggedSqlCollector.stop(); + + assertThat(exists0).isEqualTo(exists1); + assertThat(sql).hasSize(1); + + // and now, ensure that we hit the database + LoggedSqlCollector.start(); + boolean exists2 = Ebean.find(EColAB.class) + .setUseQueryCache(CacheMode.OFF) + .where() + .eq("columnB", "exists") + .exists(); + assertThat(exists2).isEqualTo(exists1); + sql = LoggedSqlCollector.stop(); + assertThat(sql).hasSize(1); + } + @Test public void findCountDifferentQueries() {