diff --git a/ebean-api/src/main/java/io/ebean/Query.java b/ebean-api/src/main/java/io/ebean/Query.java index 28cce0506..ef941aa1f 100644 --- a/ebean-api/src/main/java/io/ebean/Query.java +++ b/ebean-api/src/main/java/io/ebean/Query.java @@ -970,6 +970,25 @@ public interface Query extends CancelableQuery { @Nullable A findSingleAttribute(); + /** + * Execute the query returning a single optional attribute value. + *

+ *

Example

+ *
{@code
+   *
+   *  Optional maybeName =
+   *    new QCustomer()
+   *      .select(name)
+   *      .id.eq(42)
+   *      .status.eq(NEW)
+   *      .findSingleAttributeOrEmpty();
+   *
+   * }
+ * + * @return an optional value for the selected property + */ +
Optional findSingleAttributeOrEmpty(); + /** * Return true if this is countDistinct query. */ diff --git a/ebean-core/src/main/java/io/ebeaninternal/server/query/DefaultFetchGroupQuery.java b/ebean-core/src/main/java/io/ebeaninternal/server/query/DefaultFetchGroupQuery.java index ce8f71a53..c4a3b965b 100644 --- a/ebean-core/src/main/java/io/ebeaninternal/server/query/DefaultFetchGroupQuery.java +++ b/ebean-core/src/main/java/io/ebeaninternal/server/query/DefaultFetchGroupQuery.java @@ -305,6 +305,11 @@ final class DefaultFetchGroupQuery implements SpiFetchGroupQuery, SpiQuery throw new RuntimeException("EB102: Only select() and fetch() clause is allowed on FetchGroup"); } + @Override + public Optional findSingleAttributeOrEmpty() { + throw new RuntimeException("EB102: Only select() and fetch() clause is allowed on FetchGroup"); + } + @Override public boolean isCountDistinct() { throw new RuntimeException("EB102: Only select() and fetch() clause is allowed on FetchGroup"); diff --git a/ebean-core/src/main/java/io/ebeaninternal/server/querydefn/DefaultOrmQuery.java b/ebean-core/src/main/java/io/ebeaninternal/server/querydefn/DefaultOrmQuery.java index 9a583fdd8..0e9e5f7d4 100644 --- a/ebean-core/src/main/java/io/ebeaninternal/server/querydefn/DefaultOrmQuery.java +++ b/ebean-core/src/main/java/io/ebeaninternal/server/querydefn/DefaultOrmQuery.java @@ -1161,7 +1161,7 @@ public class DefaultOrmQuery extends AbstractQuery implements SpiQuery { // add the rawSql statement - if any if (orderByIsEmpty()) { if (rawSql != null && rawSql.getSql() != null) { - order(rawSql.getSql().getOrderBy()); + orderBy(rawSql.getSql().getOrderBy()); } } if (checkPagingOrderBy()) { @@ -1517,7 +1517,6 @@ public class DefaultOrmQuery extends AbstractQuery implements SpiQuery { } @Override - @SuppressWarnings("unchecked") public final List findSingleAttributeList() { return server.findSingleAttributeList(this); } @@ -1533,6 +1532,11 @@ public class DefaultOrmQuery extends AbstractQuery implements SpiQuery { return !list.isEmpty() ? list.get(0) : null; } + @Override + public final Optional findSingleAttributeOrEmpty() { + return Optional.ofNullable(findSingleAttribute()); + } + @Override public final T findOne() { return server.findOne(this); diff --git a/ebean-querybean/src/main/java/io/ebean/typequery/TQRootBean.java b/ebean-querybean/src/main/java/io/ebean/typequery/TQRootBean.java index bd9cd27c9..48125150e 100644 --- a/ebean-querybean/src/main/java/io/ebean/typequery/TQRootBean.java +++ b/ebean-querybean/src/main/java/io/ebean/typequery/TQRootBean.java @@ -1867,6 +1867,28 @@ public abstract class TQRootBean { return query.findSingleAttribute(); } + /** + * Execute the query returning a single optional attribute value. + *

+ *

Example

+ *
{@code
+   *
+   *  Optional maybeName =
+   *    new QCustomer()
+   *      .select(name)
+   *      .id.eq(42)
+   *      .status.eq(NEW)
+   *      .findSingleAttributeOrEmpty();
+   *
+   * }
+ * + * @return an optional value for the selected property + */ + @Nullable + public
Optional findSingleAttributeOrEmpty() { + return query.findSingleAttributeOrEmpty(); + } + /** * Execute the query processing the beans one at a time. *

diff --git a/ebean-querybean/src/test/java/org/querytest/QCustomerTest.java b/ebean-querybean/src/test/java/org/querytest/QCustomerTest.java index 1b80360bb..5c25c91e9 100644 --- a/ebean-querybean/src/test/java/org/querytest/QCustomerTest.java +++ b/ebean-querybean/src/test/java/org/querytest/QCustomerTest.java @@ -1069,6 +1069,32 @@ public class QCustomerTest { assertThat(maxDate).isNotNull(); } + @Test + public void findSingleAttributeOrEmpty() { + + Customer cust = new Customer(); + cust.setName("MaybeIExist yeah"); + cust.setStatus(Customer.Status.GOOD); + cust.setRegistered(new Date()); + cust.save(); + + Optional customerName = new QCustomer() + .select(name) + .status.eq(Customer.Status.GOOD) + .name.startsWith("MaybeIExist") + .findSingleAttributeOrEmpty(); + + assertThat(customerName).isPresent(); + + Optional customerName2 = new QCustomer() + .select(name) + .status.eq(Customer.Status.GOOD) + .name.eq("NahIDoNotExist") + .findSingleAttributeOrEmpty(); + + assertThat(customerName2).isEmpty(); + } + @Test public void testFetchByScalarValue() { diff --git a/ebean-test/src/test/java/org/tests/query/other/TestQuerySingleAttribute.java b/ebean-test/src/test/java/org/tests/query/other/TestQuerySingleAttribute.java index db02e5eda..19984b729 100644 --- a/ebean-test/src/test/java/org/tests/query/other/TestQuerySingleAttribute.java +++ b/ebean-test/src/test/java/org/tests/query/other/TestQuerySingleAttribute.java @@ -20,6 +20,7 @@ import org.tests.o2m.OmBasicParent; import java.sql.Date; import java.time.LocalDate; import java.util.List; +import java.util.Optional; import static org.assertj.core.api.Assertions.assertThat; @@ -139,6 +140,32 @@ class TestQuerySingleAttribute extends BaseTestCase { assertThat(name).isNotNull(); } + @Test + void findSingleAttributeOrEmpty() { + ResetBasicData.reset(); + + Query query = DB.find(Customer.class) + .select("name") + .where().eq("name", "Rob").query(); + + Optional name = query.findSingleAttributeOrEmpty(); + + assertThat(sqlOf(query)).contains("select t0.name from o_customer t0"); + assertThat(name).isPresent().contains("Rob"); + } + + @Test + void findSingleAttributeOrEmpty_when_empty() { + ResetBasicData.reset(); + + Query query = DB.find(Customer.class) + .select("name") + .where().eq("name", "I_Do_Not_ExistO!").query(); + + Optional name = query.findSingleAttributeOrEmpty(); + assertThat(name).isEmpty(); + } + @Test void findSingleAttributeList_with_join_column() { ResetBasicData.reset();