From 6d0556a120afa852f16d501c97f5706a3c74f0db Mon Sep 17 00:00:00 2001
From: rob bygrave
Date: Thu, 2 Aug 2018 23:18:44 +1200
Subject: [PATCH] #1460 - ENH: Add FetchGroup ... as a mechanism to specify
select() + fetch() separately from Query
Change to add generics for FetchGroup
---
src/main/java/io/ebean/ExpressionList.java | 2 +-
src/main/java/io/ebean/FetchGroup.java | 26 ++++++-------
src/main/java/io/ebean/FetchGroupBuilder.java | 30 ++++++++------
src/main/java/io/ebean/Query.java | 2 +-
src/main/java/io/ebean/XServiceProvider.java | 8 ++--
.../ebean/service/SpiFetchGroupService.java | 11 ++++--
.../server/query/DFetchGroup.java | 2 +-
.../server/query/DFetchGroupBuilder.java | 39 +++++++++++--------
.../server/query/DFetchGroupService.java | 8 ++--
.../server/querydefn/SpiFetchGroup.java | 2 +-
src/test/java/io/ebean/FetchGroupTest.java | 14 ++++---
11 files changed, 81 insertions(+), 63 deletions(-)
diff --git a/src/main/java/io/ebean/ExpressionList.java b/src/main/java/io/ebean/ExpressionList.java
index 2a2a6938b..9ce5e8d08 100644
--- a/src/main/java/io/ebean/ExpressionList.java
+++ b/src/main/java/io/ebean/ExpressionList.java
@@ -415,7 +415,7 @@ public interface ExpressionList {
/**
* Apply the fetchGroup which defines what part of the object graph to load.
*/
- Query select(FetchGroup fetchGroup);
+ Query select(FetchGroup fetchGroup);
/**
* Set whether this query uses DISTINCT.
diff --git a/src/main/java/io/ebean/FetchGroup.java b/src/main/java/io/ebean/FetchGroup.java
index 54552a227..003bd0de9 100644
--- a/src/main/java/io/ebean/FetchGroup.java
+++ b/src/main/java/io/ebean/FetchGroup.java
@@ -13,7 +13,7 @@ import javax.annotation.Nonnull;
* Select example
*
* {@code
*
- * FetchGroup fetchGroup = FetchGroup.of("name, status");
+ * FetchGroup fetchGroup = FetchGroup.of(Customer.class, "name, status");
*
* Customer.query()
* .select(fetchGroup)
@@ -24,7 +24,7 @@ import javax.annotation.Nonnull;
* Select and fetch example
* {@code
*
- * FetchGroup fetchGroup = FetchGroup
+ * FetchGroup fetchGroup = FetchGroup.of(Customer.class)
* .select("name, status")
* .fetch("contacts", "firstName, lastName, email")
* .build();
@@ -41,12 +41,12 @@ import javax.annotation.Nonnull;
*
* {@code
*
- * FetchGroup FG_ADDRESS = FetchGroup
+ * FetchGroup FG_ADDRESS = FetchGroup.of(Address.class)
* .select("line1, line2, city")
* .fetch("country", "name")
* .build();
*
- * FetchGroup FG_CUSTOMER = FetchGroup
+ * FetchGroup FG_CUSTOMER = FetchGroup.of(Customer.class)
* .select("name, version")
* .fetch("billingAddress", FG_ADDRESS)
* .build();
@@ -57,8 +57,10 @@ import javax.annotation.Nonnull;
* .findList();
*
* }
+ *
+ * @param The bean type the Fetch group can be applied to
*/
-public interface FetchGroup {
+public interface FetchGroup {
/**
* Return the FetchGroup with the given select clause.
@@ -67,7 +69,7 @@ public interface FetchGroup {
*
* {@code
*
- * FetchGroup fetchGroup = FetchGroup.of("name, status");
+ * FetchGroup fetchGroup = FetchGroup.of(Customer.class, "name, status");
*
* Customer.query()
* .select(fetchGroup)
@@ -80,8 +82,8 @@ public interface FetchGroup {
* @return The FetchGroup with the given select clause
*/
@Nonnull
- static FetchGroup of(String select) {
- return XServiceProvider.fetchGroupOf(select);
+ static FetchGroup of(Class cls, String select) {
+ return XServiceProvider.fetchGroupOf(cls, select);
}
/**
@@ -91,7 +93,7 @@ public interface FetchGroup {
*
* {@code
*
- * FetchGroup fetchGroup = FetchGroup
+ * FetchGroup fetchGroup = FetchGroup.of(Customer.class)
* .select("name, status")
* .fetch("contacts", "firstName, lastName, email")
* .build();
@@ -102,13 +104,11 @@ public interface FetchGroup {
*
* }
*
- * @param select The select clause for the FetchGroup
- *
* @return The FetchGroupBuilder with the given select clause which we will add fetch clauses to
*/
@Nonnull
- static FetchGroupBuilder select(String select) {
- return XServiceProvider.fetchGroupSelect(select);
+ static FetchGroupBuilder of(Class cls) {
+ return XServiceProvider.fetchGroupOf(cls);
}
}
diff --git a/src/main/java/io/ebean/FetchGroupBuilder.java b/src/main/java/io/ebean/FetchGroupBuilder.java
index 65ad49bbf..cfe1ebfd8 100644
--- a/src/main/java/io/ebean/FetchGroupBuilder.java
+++ b/src/main/java/io/ebean/FetchGroupBuilder.java
@@ -23,65 +23,71 @@ import javax.annotation.Nonnull;
*
* }
*/
-public interface FetchGroupBuilder {
+public interface FetchGroupBuilder {
/**
- * Fetch the path including all its properties.
+ * Specify specific properties to select (top level properties).
*/
@Nonnull
- FetchGroupBuilder fetch(String path);
+ FetchGroupBuilder select(String select);
+
+ /**
+ * Fetch all the properties at the given path.
+ */
+ @Nonnull
+ FetchGroupBuilder fetch(String path);
/**
* Fetch the path with the nested fetch group.
*/
@Nonnull
- FetchGroupBuilder fetch(String path, FetchGroup nestedGroup);
+ FetchGroupBuilder fetch(String path, FetchGroup nestedGroup);
/**
* Fetch the path using a query join with the nested fetch group.
*/
@Nonnull
- FetchGroupBuilder fetchQuery(String path, FetchGroup nestedGroup);
+ FetchGroupBuilder fetchQuery(String path, FetchGroup nestedGroup);
/**
* Fetch the path lazily with the nested fetch group.
*/
@Nonnull
- FetchGroupBuilder fetchLazy(String path, FetchGroup nestedGroup);
+ FetchGroupBuilder fetchLazy(String path, FetchGroup nestedGroup);
/**
* Fetch the path including specified properties.
*/
@Nonnull
- FetchGroupBuilder fetch(String path, String properties);
+ FetchGroupBuilder fetch(String path, String properties);
/**
* Fetch the path including all its properties using a query join.
*/
@Nonnull
- FetchGroupBuilder fetchQuery(String path);
+ FetchGroupBuilder fetchQuery(String path);
/**
* Fetch the path including specified properties using a query join.
*/
@Nonnull
- FetchGroupBuilder fetchQuery(String path, String properties);
+ FetchGroupBuilder fetchQuery(String path, String properties);
/**
* Fetch the path including all its properties lazily.
*/
@Nonnull
- FetchGroupBuilder fetchLazy(String path);
+ FetchGroupBuilder fetchLazy(String path);
/**
* Fetch the path including specified properties lazily.
*/
@Nonnull
- FetchGroupBuilder fetchLazy(String path, String properties);
+ FetchGroupBuilder fetchLazy(String path, String properties);
/**
* Build and return the FetchGroup.
*/
@Nonnull
- FetchGroup build();
+ FetchGroup build();
}
diff --git a/src/main/java/io/ebean/Query.java b/src/main/java/io/ebean/Query.java
index 350393776..8749a2213 100644
--- a/src/main/java/io/ebean/Query.java
+++ b/src/main/java/io/ebean/Query.java
@@ -400,7 +400,7 @@ public interface Query {
/**
* Apply the fetchGroup which defines what part of the object graph to load.
*/
- Query select(FetchGroup fetchGroup);
+ Query select(FetchGroup fetchGroup);
/**
* Specify a path to fetch eagerly including specific properties.
diff --git a/src/main/java/io/ebean/XServiceProvider.java b/src/main/java/io/ebean/XServiceProvider.java
index 53a81993a..81976df38 100644
--- a/src/main/java/io/ebean/XServiceProvider.java
+++ b/src/main/java/io/ebean/XServiceProvider.java
@@ -61,14 +61,14 @@ class XServiceProvider {
/**
* Return the FetchGroup with the given select clause.
*/
- static FetchGroup fetchGroupOf(String select) {
- return fetchGroupService.of(select);
+ static FetchGroup fetchGroupOf(Class cls, String select) {
+ return fetchGroupService.of(cls, select);
}
/**
* Return the FetchGroupBuilder with the given select clause.
*/
- static FetchGroupBuilder fetchGroupSelect(String select) {
- return fetchGroupService.select(select);
+ static FetchGroupBuilder fetchGroupOf(Class cls) {
+ return fetchGroupService.of(cls);
}
}
diff --git a/src/main/java/io/ebean/service/SpiFetchGroupService.java b/src/main/java/io/ebean/service/SpiFetchGroupService.java
index 813f5244d..b486d4ae1 100644
--- a/src/main/java/io/ebean/service/SpiFetchGroupService.java
+++ b/src/main/java/io/ebean/service/SpiFetchGroupService.java
@@ -10,14 +10,17 @@ public interface SpiFetchGroupService {
/**
* Return the FetchGroup with the given select clause.
+ *
+ * @param beanType The type of entity bean the fetch group is for
+ * @param select The properties to select (top level properties)
*/
- FetchGroup of(String select);
+ FetchGroup of(Class beanType, String select);
/**
* Create and return a FetchGroupBuilder starting with a select() clause.
*
- * @param select The properties to select (top level properties)
- * @return The FetchGroupBuilder to add additional fetch clauses
+ * @param beanType The type of entity bean the fetch group is for
+ * @return The FetchGroupBuilder to add additional select and fetch clauses
*/
- FetchGroupBuilder select(String select);
+ FetchGroupBuilder of(Class beanType);
}
diff --git a/src/main/java/io/ebeaninternal/server/query/DFetchGroup.java b/src/main/java/io/ebeaninternal/server/query/DFetchGroup.java
index 6bd9cbc8e..4b17e3461 100644
--- a/src/main/java/io/ebeaninternal/server/query/DFetchGroup.java
+++ b/src/main/java/io/ebeaninternal/server/query/DFetchGroup.java
@@ -6,7 +6,7 @@ import io.ebeaninternal.server.querydefn.SpiFetchGroup;
/**
* Default FetchGroup implementation.
*/
-class DFetchGroup implements SpiFetchGroup {
+class DFetchGroup implements SpiFetchGroup {
private final OrmQueryDetail detail;
diff --git a/src/main/java/io/ebeaninternal/server/query/DFetchGroupBuilder.java b/src/main/java/io/ebeaninternal/server/query/DFetchGroupBuilder.java
index 76778ee41..15c876b0d 100644
--- a/src/main/java/io/ebeaninternal/server/query/DFetchGroupBuilder.java
+++ b/src/main/java/io/ebeaninternal/server/query/DFetchGroupBuilder.java
@@ -9,39 +9,46 @@ import io.ebeaninternal.server.querydefn.SpiFetchGroup;
/**
* Default implementation of the FetchGroupBuilder.
*/
-class DFetchGroupBuilder implements FetchGroupBuilder {
+class DFetchGroupBuilder implements FetchGroupBuilder {
private static final FetchConfig FETCH_QUERY = new FetchConfig().query();
private static final FetchConfig FETCH_LAZY = new FetchConfig().lazy();
- private OrmQueryDetail detail;
+ private final OrmQueryDetail detail;
- DFetchGroupBuilder(OrmQueryDetail detail) {
- this.detail = detail;
+ DFetchGroupBuilder() {
+ this.detail = new OrmQueryDetail();
}
@Override
- public FetchGroupBuilder fetch(String path) {
+ public FetchGroupBuilder select(String select) {
+ detail.select(select);
+ return this;
+ }
+
+ @Override
+ public FetchGroupBuilder fetch(String path) {
detail.fetch(path, null, null);
return this;
}
@Override
- public FetchGroupBuilder fetch(String path, FetchGroup nestedGroup) {
+ public FetchGroupBuilder fetch(String path, FetchGroup nestedGroup) {
return fetchNested(path, nestedGroup, null);
}
+
@Override
- public FetchGroupBuilder fetchQuery(String path, FetchGroup nestedGroup) {
+ public FetchGroupBuilder fetchQuery(String path, FetchGroup nestedGroup) {
return fetchNested(path, nestedGroup, FETCH_QUERY);
}
@Override
- public FetchGroupBuilder fetchLazy(String path, FetchGroup nestedGroup) {
+ public FetchGroupBuilder fetchLazy(String path, FetchGroup nestedGroup) {
return fetchNested(path, nestedGroup, FETCH_LAZY);
}
- private FetchGroupBuilder fetchNested(String path, FetchGroup nestedGroup, FetchConfig fetchConfig) {
+ private FetchGroupBuilder fetchNested(String path, FetchGroup nestedGroup, FetchConfig fetchConfig) {
OrmQueryDetail nestedDetail = ((SpiFetchGroup) nestedGroup).underlying();
detail.addNested(path, nestedDetail, fetchConfig);
@@ -49,37 +56,37 @@ class DFetchGroupBuilder implements FetchGroupBuilder {
}
@Override
- public FetchGroupBuilder fetchQuery(String path) {
+ public FetchGroupBuilder fetchQuery(String path) {
detail.fetch(path, null, FETCH_QUERY);
return this;
}
@Override
- public FetchGroupBuilder fetchLazy(String path) {
+ public FetchGroupBuilder fetchLazy(String path) {
detail.fetch(path, null, FETCH_LAZY);
return this;
}
@Override
- public FetchGroupBuilder fetch(String path, String properties) {
+ public FetchGroupBuilder fetch(String path, String properties) {
detail.fetch(path, properties, null);
return this;
}
@Override
- public FetchGroupBuilder fetchQuery(String path, String properties) {
+ public FetchGroupBuilder fetchQuery(String path, String properties) {
detail.fetch(path, properties, FETCH_QUERY);
return this;
}
@Override
- public FetchGroupBuilder fetchLazy(String path, String properties) {
+ public FetchGroupBuilder fetchLazy(String path, String properties) {
detail.fetch(path, properties, FETCH_LAZY);
return this;
}
@Override
- public FetchGroup build() {
- return new DFetchGroup(detail);
+ public FetchGroup build() {
+ return new DFetchGroup<>(detail);
}
}
diff --git a/src/main/java/io/ebeaninternal/server/query/DFetchGroupService.java b/src/main/java/io/ebeaninternal/server/query/DFetchGroupService.java
index 62555997d..3dc53a83a 100644
--- a/src/main/java/io/ebeaninternal/server/query/DFetchGroupService.java
+++ b/src/main/java/io/ebeaninternal/server/query/DFetchGroupService.java
@@ -11,13 +11,13 @@ import io.ebeaninternal.server.querydefn.OrmQueryDetail;
public final class DFetchGroupService implements SpiFetchGroupService {
@Override
- public FetchGroup of(String select) {
- return new DFetchGroup(detail(select));
+ public FetchGroup of(Class cls, String select) {
+ return new DFetchGroup<>(detail(select));
}
@Override
- public FetchGroupBuilder select(String select) {
- return new DFetchGroupBuilder(detail(select));
+ public FetchGroupBuilder of(Class cls) {
+ return new DFetchGroupBuilder<>();
}
private OrmQueryDetail detail(String select) {
diff --git a/src/main/java/io/ebeaninternal/server/querydefn/SpiFetchGroup.java b/src/main/java/io/ebeaninternal/server/querydefn/SpiFetchGroup.java
index 05935e25c..35f622f03 100644
--- a/src/main/java/io/ebeaninternal/server/querydefn/SpiFetchGroup.java
+++ b/src/main/java/io/ebeaninternal/server/querydefn/SpiFetchGroup.java
@@ -5,7 +5,7 @@ import io.ebean.FetchGroup;
/**
* Service API of FetchGroup.
*/
-public interface SpiFetchGroup extends FetchGroup {
+public interface SpiFetchGroup extends FetchGroup {
/**
* Return the detail to use for query execution.
diff --git a/src/test/java/io/ebean/FetchGroupTest.java b/src/test/java/io/ebean/FetchGroupTest.java
index 91bf229b8..148cc7230 100644
--- a/src/test/java/io/ebean/FetchGroupTest.java
+++ b/src/test/java/io/ebean/FetchGroupTest.java
@@ -2,6 +2,8 @@ package io.ebean;
import org.ebeantest.LoggedSqlCollector;
import org.junit.Test;
+import org.tests.model.basic.Address;
+import org.tests.model.basic.Contact;
import org.tests.model.basic.Customer;
import org.tests.model.basic.ResetBasicData;
@@ -14,7 +16,7 @@ public class FetchGroupTest extends BaseTestCase {
@Test
public void simple() {
- FetchGroup fetch = FetchGroup.of("name, status");
+ FetchGroup fetch = FetchGroup.of(Customer.class, "name, status");
Query query = Customer.find
.query()
@@ -33,7 +35,7 @@ public class FetchGroupTest extends BaseTestCase {
ResetBasicData.reset();
- FetchGroup fetch = FetchGroup
+ FetchGroup fetch = FetchGroup.of(Customer.class)
.select("name, status")
.fetchQuery("contacts", "firstName, lastName, email")
.build();
@@ -59,9 +61,9 @@ public class FetchGroupTest extends BaseTestCase {
ResetBasicData.reset();
- FetchGroup CT_NAME = FetchGroup.of("firstName, lastName, email");
+ FetchGroup CT_NAME = FetchGroup.of(Contact.class, "firstName, lastName, email");
- FetchGroup fetch = FetchGroup
+ FetchGroup fetch = FetchGroup.of(Customer.class)
.select("name")
.fetchQuery("contacts", CT_NAME)
.build();
@@ -86,12 +88,12 @@ public class FetchGroupTest extends BaseTestCase {
ResetBasicData.reset();
- FetchGroup FGAddress = FetchGroup
+ FetchGroup FGAddress = FetchGroup.of(Address.class)
.select("line1, line2, city")
.fetch("country", "name")
.build();
- FetchGroup FBCustomer = FetchGroup
+ FetchGroup FBCustomer = FetchGroup.of(Customer.class)
.select("name, version")
.fetch("billingAddress", FGAddress)
.build();