mirror of
https://github.com/ebean-orm/ebean.git
synced 2024-04-21 10:51:47 +00:00
Add support for dynamic formula with includes
e.g.
DB.find(ChildPerson.class)
.select("name, coalesce(someBean, parent.someBean) as effectiveBean") // include parent
.findList();
This commit is contained in:
+10
-1
@@ -2,14 +2,18 @@ package io.ebeaninternal.server.deploy;
|
||||
|
||||
import io.ebeaninternal.server.query.SqlBeanLoad;
|
||||
|
||||
import java.util.Set;
|
||||
|
||||
@SuppressWarnings("rawtypes")
|
||||
public final class DynamicPropertyAggregationFormulaMTO extends DynamicPropertyAggregationFormula {
|
||||
|
||||
private final BeanPropertyAssocOne prop;
|
||||
private final Set<String> includes;
|
||||
|
||||
DynamicPropertyAggregationFormulaMTO(BeanPropertyAssocOne prop, String name, String parsedFormula, boolean aggregate, BeanProperty asTarget, String alias) {
|
||||
DynamicPropertyAggregationFormulaMTO(BeanPropertyAssocOne prop, String name, String parsedFormula, boolean aggregate, BeanProperty asTarget, String alias, Set<String> includes) {
|
||||
super(name, prop.idScalarType(), parsedFormula, aggregate, asTarget, alias);
|
||||
this.prop = prop;
|
||||
this.includes = includes;
|
||||
}
|
||||
|
||||
@Override
|
||||
@@ -17,6 +21,11 @@ public final class DynamicPropertyAggregationFormulaMTO extends DynamicPropertyA
|
||||
return true;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void extraIncludes(Set<String> predicateIncludes) {
|
||||
predicateIncludes.addAll(includes);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void load(SqlBeanLoad sqlBeanLoad) {
|
||||
Object value;
|
||||
|
||||
@@ -5,6 +5,7 @@ import io.ebeaninternal.server.el.ElPropertyDeploy;
|
||||
import io.ebeaninternal.server.query.STreeProperty;
|
||||
|
||||
import java.sql.Types;
|
||||
import java.util.Set;
|
||||
|
||||
final class FormulaPropertyPath {
|
||||
|
||||
@@ -18,6 +19,7 @@ final class FormulaPropertyPath {
|
||||
private final String internalExpression;
|
||||
private final ElPropertyDeploy firstProp;
|
||||
private final String parsedAggregation;
|
||||
private final Set<String> includes;
|
||||
private boolean countDistinct;
|
||||
private String cast;
|
||||
private String alias;
|
||||
@@ -47,6 +49,7 @@ final class FormulaPropertyPath {
|
||||
// fetch("machineStats", "sum(hours), sum(totalKms)")
|
||||
parsed = parsed.replace("${}", "${" + path + "}");
|
||||
}
|
||||
this.includes = parser.includes();
|
||||
this.parsedAggregation = buildFormula(parsed);
|
||||
this.firstProp = parser.firstProp();
|
||||
}
|
||||
@@ -129,7 +132,7 @@ final class FormulaPropertyPath {
|
||||
@SuppressWarnings("rawtypes")
|
||||
private DynamicPropertyAggregationFormula createManyToOne(BeanProperty property) {
|
||||
String logicalName = logicalName();
|
||||
return new DynamicPropertyAggregationFormulaMTO((BeanPropertyAssocOne) property, logicalName, parsedAggregation, isAggregate(), target(logicalName), alias);
|
||||
return new DynamicPropertyAggregationFormulaMTO((BeanPropertyAssocOne) property, logicalName, parsedAggregation, isAggregate(), target(logicalName), alias, includes);
|
||||
}
|
||||
|
||||
private BeanProperty target(String logicalName) {
|
||||
|
||||
@@ -6,6 +6,7 @@ import io.ebeaninternal.server.deploy.DbReadContext;
|
||||
import io.ebeaninternal.server.deploy.DbSqlContext;
|
||||
|
||||
import java.util.List;
|
||||
import java.util.Set;
|
||||
|
||||
/**
|
||||
* A property in the SQL Tree.
|
||||
@@ -28,7 +29,7 @@ public interface STreeProperty extends ScalarDataReader<Object> {
|
||||
* Return true if the property is the Id.
|
||||
*/
|
||||
boolean isId();
|
||||
|
||||
|
||||
/**
|
||||
* Returns true, if this is a lob property from db-perspective.
|
||||
*/
|
||||
@@ -96,4 +97,7 @@ public interface STreeProperty extends ScalarDataReader<Object> {
|
||||
*/
|
||||
void appendFrom(DbSqlContext ctx, SqlJoinType joinType, String manyWhere);
|
||||
|
||||
default void extraIncludes(Set<String> predicateIncludes) {
|
||||
// do nothing
|
||||
}
|
||||
}
|
||||
|
||||
@@ -406,7 +406,7 @@ public final class SqlTreeBuilder {
|
||||
}
|
||||
|
||||
int basePos = propName.indexOf('.');
|
||||
if (basePos > -1) {
|
||||
if (basePos > -1 && !propName.contains(" as ")) {
|
||||
// property on an embedded bean. Embedded beans do not yet
|
||||
// support being partially populated so we include the
|
||||
// 'base' property and make sure we only do that once
|
||||
@@ -457,6 +457,9 @@ public final class SqlTreeBuilder {
|
||||
}
|
||||
} else {
|
||||
selectProps.add(p);
|
||||
if (p.isAggregationManyToOne()) {
|
||||
p.extraIncludes(predicates.predicateIncludes());
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,9 +1,10 @@
|
||||
package org.tests.family;
|
||||
|
||||
import io.ebean.xtest.BaseTestCase;
|
||||
import io.ebean.DB;
|
||||
import io.ebean.xtest.IgnorePlatform;
|
||||
import io.ebean.annotation.Platform;
|
||||
import io.ebean.test.LoggedSql;
|
||||
import io.ebean.xtest.BaseTestCase;
|
||||
import io.ebean.xtest.IgnorePlatform;
|
||||
import io.ebeaninternal.server.deploy.BeanDescriptor;
|
||||
import io.ebeaninternal.server.deploy.BeanProperty;
|
||||
import io.ebeaninternal.server.deploy.BeanPropertyAssocOne;
|
||||
@@ -13,6 +14,11 @@ import org.tests.model.family.ChildPerson;
|
||||
import org.tests.model.family.GrandParentPerson;
|
||||
import org.tests.model.family.ParentPerson;
|
||||
|
||||
import java.util.HashMap;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
|
||||
import static org.assertj.core.api.Assertions.assertThat;
|
||||
import static org.junit.jupiter.api.Assertions.*;
|
||||
|
||||
|
||||
@@ -97,6 +103,10 @@ public class TestInheritance extends BaseTestCase {
|
||||
|
||||
|
||||
server().save(grandparent1);
|
||||
|
||||
testMyDynamicFormulaWithIncludes();
|
||||
testMyDynamicFormulaWithIncludesAndFetchJoin();
|
||||
|
||||
// Test setup complete, so retrieve bean from db
|
||||
//grandparent1 = server().find(GrandParentPerson.class).setId(grandparent1.getIdentifier()).where()
|
||||
// .in("effectiveBean.id",2,null) // geht nicht!
|
||||
@@ -222,6 +232,49 @@ public class TestInheritance extends BaseTestCase {
|
||||
DB.find(EBasic.class).delete();
|
||||
}
|
||||
|
||||
private void testMyDynamicFormulaWithIncludes() {
|
||||
LoggedSql.start();
|
||||
List<ChildPerson> children = DB.find(ChildPerson.class)
|
||||
.select("name, coalesce(someBean, parent.someBean) as effectiveBean") // include parent
|
||||
.findList();
|
||||
|
||||
Map<String,EBasic> childToBasic = new HashMap<>();
|
||||
for (ChildPerson child : children) {
|
||||
childToBasic.put(child.getName(), child.getEffectiveBean());
|
||||
}
|
||||
|
||||
assertThat(childToBasic.get("Fred").getName()).isEqualTo("An other Bean");
|
||||
assertThat(childToBasic.get("Julia").getName()).isEqualTo("A Bean");
|
||||
assertThat(childToBasic.get("Roland")).isNull();
|
||||
List<String> sql = LoggedSql.stop();
|
||||
|
||||
assertThat(sql).hasSize(2);
|
||||
assertThat(sql.get(0)).contains("select t0.identifier, t0.name, coalesce(t0.some_bean_id, t1.some_bean_id) effectiveBean from child_person t0 left join parent_person t1 on t1.identifier = t0.parent_identifier");
|
||||
assertThat(sql.get(1)).contains("select t0.id, t0.status, t0.name, t0.description, t0.some_date from e_basic t0 where t0.id");
|
||||
}
|
||||
|
||||
private void testMyDynamicFormulaWithIncludesAndFetchJoin() {
|
||||
LoggedSql.start();
|
||||
List<ChildPerson> children = DB.find(ChildPerson.class)
|
||||
.select("name, coalesce(someBean, parent.someBean) as effectiveBean") // include parent
|
||||
.fetch("parent", "name, familyName")
|
||||
.findList();
|
||||
|
||||
Map<String,EBasic> childToBasic = new HashMap<>();
|
||||
for (ChildPerson child : children) {
|
||||
childToBasic.put(child.getName(), child.getEffectiveBean());
|
||||
}
|
||||
|
||||
assertThat(childToBasic.get("Fred").getName()).isEqualTo("An other Bean");
|
||||
assertThat(childToBasic.get("Julia").getName()).isEqualTo("A Bean");
|
||||
assertThat(childToBasic.get("Roland")).isNull();
|
||||
List<String> sql = LoggedSql.stop();
|
||||
|
||||
assertThat(sql).hasSize(2);
|
||||
assertThat(sql.get(0)).contains("select t0.identifier, t0.name, coalesce(t0.some_bean_id, t1.some_bean_id) effectiveBean, t1.identifier, t1.name, t1.family_name from child_person t0 left join parent_person t1 on t1.identifier = t0.parent_identifier");
|
||||
assertThat(sql.get(1)).contains("select t0.id, t0.status, t0.name, t0.description, t0.some_date from e_basic t0 where t0.id");
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testFindCount() {
|
||||
EBasic basicA = new EBasic();
|
||||
|
||||
Reference in New Issue
Block a user