mirror of
https://github.com/ebean-orm/ebean.git
synced 2024-04-21 10:51:47 +00:00
#2768 - ENH: Add eqIfPresent() - a helper expression for fluid style when some EQ are optional
This commit is contained in:
@@ -385,7 +385,7 @@ public interface ExpressionList<T> {
|
||||
|
||||
/**
|
||||
* Executes the query returning a set of values for a single property.
|
||||
*
|
||||
* <p>
|
||||
* This can be used to cache sets.
|
||||
*
|
||||
* @return a HashSet of values for the selegted property
|
||||
@@ -835,6 +835,20 @@ public interface ExpressionList<T> {
|
||||
*/
|
||||
ExpressionList<T> eq(String propertyName, Object value);
|
||||
|
||||
/**
|
||||
* Is EQUAL TO if value is non-null and otherwise no expression is added to the query.
|
||||
* <p>
|
||||
* This is the EQUAL TO equivalent to {@link #inOrEmpty(String, Collection)} where the expression/predicate
|
||||
* is only added when the value is non-null.
|
||||
* <p>
|
||||
* This is effectively a helper method that allows a query to be built in fluid style where some predicates are
|
||||
* effectively optional. We can use <code>eqIfPresent()</code> rather than having a separate if block.
|
||||
* <p>
|
||||
* Another option is to instead globally use {@link io.ebean.config.DatabaseConfig#setExpressionEqualsWithNullAsNoop(boolean)}
|
||||
* but that is not always desirable.
|
||||
*/
|
||||
ExpressionList<T> eqIfPresent(String propertyName, @Nullable Object value);
|
||||
|
||||
/**
|
||||
* Equal To or Null - property is equal to a given value or null.
|
||||
*/
|
||||
|
||||
@@ -798,6 +798,11 @@ public class DefaultExpressionList<T> implements SpiExpressionList<T> {
|
||||
return add(expr.eq(propertyName, value));
|
||||
}
|
||||
|
||||
@Override
|
||||
public ExpressionList<T> eqIfPresent(String propertyName, @Nullable Object value) {
|
||||
return value == null ? this : add(expr.eq(propertyName, value));
|
||||
}
|
||||
|
||||
@Override
|
||||
public ExpressionList<T> eqOrNull(String propertyName, Object value) {
|
||||
return add(expr.eqOrNull(propertyName, value));
|
||||
|
||||
@@ -309,6 +309,11 @@ final class JunctionExpression<T> implements SpiJunction<T>, SpiExpression, Expr
|
||||
return exprList.eq(propertyName, value);
|
||||
}
|
||||
|
||||
@Override
|
||||
public ExpressionList<T> eqIfPresent(String propertyName, @Nullable Object value) {
|
||||
return value == null ? this : exprList.eq(propertyName, value);
|
||||
}
|
||||
|
||||
@Override
|
||||
public ExpressionList<T> eqOrNull(String propertyName, Object value) {
|
||||
return exprList.eqOrNull(propertyName, value);
|
||||
|
||||
@@ -1,5 +1,6 @@
|
||||
package io.ebean.typequery;
|
||||
|
||||
import io.avaje.lang.Nullable;
|
||||
import io.ebean.Query;
|
||||
|
||||
import java.util.Collection;
|
||||
@@ -82,6 +83,25 @@ public abstract class PBaseValueEqual<R, T> extends TQPropertyBase<R> {
|
||||
return _root;
|
||||
}
|
||||
|
||||
/**
|
||||
* Is equal to if value is non-null and otherwise no expression is added to the query.
|
||||
* <p>
|
||||
* That is, only add the EQUAL TO predicate if the value is not null.
|
||||
* <p>
|
||||
* This is the EQUAL TO equivalent to {@link #inOrEmpty(Collection)} where the expression/predicate
|
||||
* is only added to the query when the value is non-null.
|
||||
* <p>
|
||||
* This is effectively a helper method that allows a query to be built in fluid style where some predicates are
|
||||
* effectively optional. We can use <code>eqIfPresent()</code> rather than having a separate if block.
|
||||
*
|
||||
* @param value the equal to bind value
|
||||
* @return the root query bean instance
|
||||
*/
|
||||
public final R eqIfPresent(@Nullable T value) {
|
||||
expr().eqIfPresent(_name, value);
|
||||
return _root;
|
||||
}
|
||||
|
||||
/**
|
||||
* Is equal to or Null.
|
||||
*
|
||||
@@ -247,7 +267,7 @@ public abstract class PBaseValueEqual<R, T> extends TQPropertyBase<R> {
|
||||
public final R isIn(Query<?> subQuery) {
|
||||
return in(subQuery);
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Is NOT in the result of a subquery.
|
||||
*
|
||||
|
||||
@@ -1,17 +1,20 @@
|
||||
package org.querytest;
|
||||
|
||||
import io.ebean.DB;
|
||||
import io.ebean.test.LoggedSql;
|
||||
import org.example.domain.MyInner;
|
||||
import org.example.domain.query.QMyInner;
|
||||
import org.junit.jupiter.api.Test;
|
||||
|
||||
import java.util.List;
|
||||
import java.util.Optional;
|
||||
|
||||
import static org.assertj.core.api.Assertions.assertThat;
|
||||
|
||||
class MyInnerTest {
|
||||
|
||||
@Test
|
||||
void insert_and_find() {
|
||||
|
||||
MyInner myInner = new MyInner()
|
||||
.id(42).one("one").description("foo");
|
||||
|
||||
@@ -26,5 +29,25 @@ class MyInnerTest {
|
||||
.findOne();
|
||||
|
||||
assertThat(found2).isNotNull();
|
||||
|
||||
LoggedSql.start();
|
||||
|
||||
MyInner found3 = new QMyInner()
|
||||
.one.eqIfPresent("one")
|
||||
.findOne();
|
||||
|
||||
assertThat(found3).isNotNull();
|
||||
|
||||
MyInner found4 = new QMyInner()
|
||||
.one.eqIfPresent(null)
|
||||
.description.eqIfPresent("foo")
|
||||
.findOne();
|
||||
|
||||
assertThat(found4).isNotNull();
|
||||
|
||||
List<String> sql = LoggedSql.stop();
|
||||
assertThat(sql).hasSize(2);
|
||||
assertThat(sql.get(0)).contains("select t0.id, t0.one, t0.id, t0.one, t0.description from my_inner t0 where t0.one = ?;");
|
||||
assertThat(sql.get(1)).contains("select t0.id, t0.one, t0.id, t0.one, t0.description from my_inner t0 where t0.description = ?;");
|
||||
}
|
||||
}
|
||||
|
||||
@@ -23,6 +23,52 @@ public class TestQueryIsNull extends BaseTestCase {
|
||||
assertThat(query.getGeneratedSql()).contains("name is null");
|
||||
}
|
||||
|
||||
@Test
|
||||
void query_defaultNullToIsNull() {
|
||||
ResetBasicData.reset();
|
||||
|
||||
Query<Order> query = DB.find(Order.class).select("id, status")
|
||||
.where().eq("status", null).query();
|
||||
query.findList();
|
||||
|
||||
assertThat(query.getGeneratedSql()).isEqualTo("select t0.id, t0.status from o_order t0 where t0.status is null");
|
||||
}
|
||||
|
||||
@Test
|
||||
void query_eqIfPresent() {
|
||||
ResetBasicData.reset();
|
||||
|
||||
Query<Order> query = DB.find(Order.class).select("id, status")
|
||||
.where().eqIfPresent("status", null).query();
|
||||
query.findList();
|
||||
|
||||
assertThat(query.getGeneratedSql()).isEqualTo("select t0.id, t0.status from o_order t0");
|
||||
|
||||
Query<Order> query1 = DB.find(Order.class).select("id, status")
|
||||
.where().eqIfPresent("status", null).isNull("shipDate").query();
|
||||
query1.findList();
|
||||
|
||||
assertThat(query1.getGeneratedSql()).isEqualTo("select t0.id, t0.status from o_order t0 where t0.ship_date is null");
|
||||
|
||||
Query<Order> query2 = DB.find(Order.class).select("id, status")
|
||||
.where().isNotNull("orderDate").eqIfPresent("status", null).query();
|
||||
query2.findList();
|
||||
|
||||
assertThat(query2.getGeneratedSql()).isEqualTo("select t0.id, t0.status from o_order t0 where t0.order_date is not null");
|
||||
|
||||
Query<Order> query3 = DB.find(Order.class).select("id, status")
|
||||
.where().isNotNull("orderDate").eqIfPresent("status", null).isNull("shipDate").query();
|
||||
query3.findList();
|
||||
|
||||
assertThat(query3.getGeneratedSql()).isEqualTo("select t0.id, t0.status from o_order t0 where t0.order_date is not null and t0.ship_date is null");
|
||||
|
||||
Query<Order> query4 = DB.find(Order.class).select("id, status")
|
||||
.where().isNotNull("orderDate").eqIfPresent("status", Order.Status.NEW).isNull("shipDate").query();
|
||||
query4.findList();
|
||||
|
||||
assertThat(query4.getGeneratedSql()).isEqualTo("select t0.id, t0.status from o_order t0 where t0.order_date is not null and t0.status = ? and t0.ship_date is null");
|
||||
}
|
||||
|
||||
@Test
|
||||
public void isNotNull_when_OneToMany_expect_existsSubquery() {
|
||||
ResetBasicData.reset();
|
||||
|
||||
Reference in New Issue
Block a user