diff --git a/src/main/java/com/avaje/ebean/FetchConfig.java b/src/main/java/com/avaje/ebean/FetchConfig.java index b885ce3ff..bf2904531 100644 --- a/src/main/java/com/avaje/ebean/FetchConfig.java +++ b/src/main/java/com/avaje/ebean/FetchConfig.java @@ -249,4 +249,22 @@ public class FetchConfig implements Serializable { return queryAll; } + @Override + public boolean equals(Object o) { + if (this == o) return true; + if (o == null || getClass() != o.getClass()) return false; + + FetchConfig that = (FetchConfig) o; + if (lazyBatchSize != that.lazyBatchSize) return false; + if (queryBatchSize != that.queryBatchSize) return false; + return queryAll == that.queryAll; + } + + @Override + public int hashCode() { + int result = lazyBatchSize; + result = 92821 * result + queryBatchSize; + result = 92821 * result + (queryAll ? 1 : 0); + return result; + } } diff --git a/src/main/java/com/avaje/ebeaninternal/api/SpiQuery.java b/src/main/java/com/avaje/ebeaninternal/api/SpiQuery.java index 8a472a7d0..08bd5b9d4 100644 --- a/src/main/java/com/avaje/ebeaninternal/api/SpiQuery.java +++ b/src/main/java/com/avaje/ebeaninternal/api/SpiQuery.java @@ -338,7 +338,7 @@ public interface SpiQuery extends Query { /** * Convert joins as necessary to query joins etc. */ - void convertJoins(int queryBatchSize); + void convertJoins(); /** * Return the TransactionContext. diff --git a/src/main/java/com/avaje/ebeaninternal/server/core/DefaultServer.java b/src/main/java/com/avaje/ebeaninternal/server/core/DefaultServer.java index db55f32cf..eba6fd89d 100644 --- a/src/main/java/com/avaje/ebeaninternal/server/core/DefaultServer.java +++ b/src/main/java/com/avaje/ebeaninternal/server/core/DefaultServer.java @@ -31,7 +31,6 @@ import com.avaje.ebeaninternal.api.SpiBackgroundExecutor; import com.avaje.ebeaninternal.api.SpiEbeanPlugin; import com.avaje.ebeaninternal.api.SpiEbeanServer; import com.avaje.ebeaninternal.api.SpiQuery; -import com.avaje.ebeaninternal.api.SpiQuery.Mode; import com.avaje.ebeaninternal.api.SpiQuery.Type; import com.avaje.ebeaninternal.api.SpiSqlQuery; import com.avaje.ebeaninternal.api.SpiTransaction; @@ -1065,7 +1064,7 @@ public final class DefaultServer implements SpiServer, SpiEbeanServer { } OrmQueryRequest request = new OrmQueryRequest(this, queryEngine, query, desc, (SpiTransaction) t); - request.prepareQuery(queryBatchSize); + request.prepareQuery(); return request; } diff --git a/src/main/java/com/avaje/ebeaninternal/server/core/OrmQueryRequest.java b/src/main/java/com/avaje/ebeaninternal/server/core/OrmQueryRequest.java index 69288b7be..c3666a8bf 100644 --- a/src/main/java/com/avaje/ebeaninternal/server/core/OrmQueryRequest.java +++ b/src/main/java/com/avaje/ebeaninternal/server/core/OrmQueryRequest.java @@ -148,12 +148,11 @@ public final class OrmQueryRequest extends BeanRequest implements BeanQueryRe /** * Prepare the query and calculate the query plan key. */ - public void prepareQuery(int queryBatchSize) { + public void prepareQuery() { adapterPreQuery(); - // determine extra joins required to support where clause predicates on *ToMany properties - query.convertJoins(queryBatchSize); + query.convertJoins(); this.queryJoins = query.removeQueryJoins(); this.lazyJoins = query.removeLazyJoins(); this.queryPlanKey = query.prepare(this); diff --git a/src/main/java/com/avaje/ebeaninternal/server/querydefn/DefaultOrmQuery.java b/src/main/java/com/avaje/ebeaninternal/server/querydefn/DefaultOrmQuery.java index 7d05cec6f..71ad5a8f3 100644 --- a/src/main/java/com/avaje/ebeaninternal/server/querydefn/DefaultOrmQuery.java +++ b/src/main/java/com/avaje/ebeaninternal/server/querydefn/DefaultOrmQuery.java @@ -375,10 +375,7 @@ public class DefaultOrmQuery implements SpiQuery { return expressionFactory; } - /** - * Return true if the where expressions contains a many property. - */ - private void initManyWhereJoins() { + private void createExtraJoinsToSupportManyWhereClause() { manyWhereJoins = new ManyWhereJoins(); if (whereExpressions != null) { whereExpressions.containsMany(beanDescriptor, manyWhereJoins); @@ -388,6 +385,9 @@ public class DefaultOrmQuery implements SpiQuery { } } + /** + * Return the extra joins required to support the where clause for 'Many' properties. + */ public ManyWhereJoins getManyWhereJoins() { return manyWhereJoins; } @@ -442,32 +442,30 @@ public class DefaultOrmQuery implements SpiQuery { this.lazyLoadManyPath = lazyLoadManyPath; } + @Override + public void convertJoins() { + + createExtraJoinsToSupportManyWhereClause(); + markQueryJoins(); + } + + /** + * Limit the number of fetch joins to Many properties, mark as query joins as needed. + */ + private void markQueryJoins() { + detail.markQueryJoins(beanDescriptor, lazyLoadManyPath, isAllowOneManyFetch()); + } + private boolean isAllowOneManyFetch() { if (Mode.LAZYLOAD_MANY.equals(getMode())) { return false; - } else if (hasMaxRowsOrFirstRow() && !isRawSql() && !isSqlSelect()) { return false; } - return true; } - @Override - public void convertJoins(int queryBatchSize) { - initManyWhereJoins(); - convertManyFetchJoinsToQueryJoins(queryBatchSize); - } - - /** - * Convert any many joins fetch joins to query joins. - */ - private void convertManyFetchJoinsToQueryJoins(int queryBatch) { - boolean allowOne = isAllowOneManyFetch(); - detail.convertManyFetchJoinsToQueryJoins(beanDescriptor, lazyLoadManyPath, allowOne, queryBatch); - } - protected void setOrmQueryDetail(OrmQueryDetail detail) { this.detail = detail; } diff --git a/src/main/java/com/avaje/ebeaninternal/server/querydefn/OrmQueryDetail.java b/src/main/java/com/avaje/ebeaninternal/server/querydefn/OrmQueryDetail.java index 4f6383c3b..d96c7f91f 100644 --- a/src/main/java/com/avaje/ebeaninternal/server/querydefn/OrmQueryDetail.java +++ b/src/main/java/com/avaje/ebeaninternal/server/querydefn/OrmQueryDetail.java @@ -7,7 +7,6 @@ import com.avaje.ebeaninternal.server.deploy.BeanPropertyAssoc; import com.avaje.ebeaninternal.server.el.ElPropertyDeploy; import com.avaje.ebeaninternal.server.el.ElPropertyValue; import com.avaje.ebeaninternal.server.query.SplitName; -import org.jetbrains.annotations.NotNull; import javax.persistence.PersistenceException; import java.io.Serializable; @@ -38,13 +37,12 @@ public class OrmQueryDetail implements Serializable { /** * Root level properties. */ - @NotNull private OrmQueryProperties baseProps = new OrmQueryProperties(); /** * Contains the fetch/lazy/query joins and their properties. */ - private LinkedHashMap fetchPaths = new LinkedHashMap(8); + private LinkedHashMap fetchPaths = new LinkedHashMap(); /** * Return a deep copy of the OrmQueryDetail. @@ -302,7 +300,7 @@ public class OrmQueryDetail implements Serializable { public void sortFetchPaths(BeanDescriptor d) { - LinkedHashMap sorted = new LinkedHashMap(fetchPaths.size()); + LinkedHashMap sorted = new LinkedHashMap(); for (OrmQueryProperties p : fetchPaths.values()) { sortFetchPaths(d, p, sorted); @@ -311,8 +309,7 @@ public class OrmQueryDetail implements Serializable { fetchPaths = sorted; } - private void sortFetchPaths(BeanDescriptor d, OrmQueryProperties p, - LinkedHashMap sorted) { + private void sortFetchPaths(BeanDescriptor d, OrmQueryProperties p, LinkedHashMap sorted) { String path = p.getPath(); if (!sorted.containsKey(path)) { @@ -325,8 +322,7 @@ public class OrmQueryDetail implements Serializable { if (parentProp == null) { ElPropertyValue el = d.getElGetValue(parentPath); if (el == null) { - String msg = "Path [" + parentPath + "] not valid from " + d.getFullName(); - throw new PersistenceException(msg); + throw new PersistenceException("Path [" + parentPath + "] not valid from " + d.getFullName()); } // add a missing parent path just fetching the Id property BeanPropertyAssoc assocOne = (BeanPropertyAssoc) el.getBeanProperty(); @@ -340,12 +336,9 @@ public class OrmQueryDetail implements Serializable { } /** - * Convert 'fetch joins' to 'many' properties over to 'query joins'. + * Mark 'fetch joins' to 'many' properties over to 'query joins' where needed. */ - public void convertManyFetchJoinsToQueryJoins(BeanDescriptor beanDescriptor, String lazyLoadManyPath, - boolean allowOne, int queryBatch) { - - ArrayList manyChunks = new ArrayList(3); + public void markQueryJoins(BeanDescriptor beanDescriptor, String lazyLoadManyPath, boolean allowOne) { // the name of the many fetch property if there is one String manyFetchProperty = null; @@ -369,16 +362,11 @@ public class OrmQueryDetail implements Serializable { manyFetchProperty = fetchPath; } else { // convert this one over to a 'query join' - manyChunks.add(chunk); + chunk.markForQueryJoin(); } } } } - - for (int i = 0; i < manyChunks.size(); i++) { - // convert 'fetch joins' over to 'query joins' - manyChunks.get(i).setQueryFetch(queryBatch, true); - } } /** diff --git a/src/main/java/com/avaje/ebeaninternal/server/querydefn/OrmQueryProperties.java b/src/main/java/com/avaje/ebeaninternal/server/querydefn/OrmQueryProperties.java index 625537773..6697ae3b4 100644 --- a/src/main/java/com/avaje/ebeaninternal/server/querydefn/OrmQueryProperties.java +++ b/src/main/java/com/avaje/ebeaninternal/server/querydefn/OrmQueryProperties.java @@ -28,35 +28,27 @@ public class OrmQueryProperties implements Serializable { private static final long serialVersionUID = -8785582703966455658L; + protected static final FetchConfig DEFAULT_FETCH = new FetchConfig(); + private final String parentPath; private final String path; private final String rawProperties; private final String trimmedProperties; - /** - * NB: -1 means no +query, 0 means use the default batch size. - */ - private int queryFetchBatch = -1; - private boolean queryFetchAll; + private final LinkedHashSet included; + + private final FetchConfig fetchConfig; /** - * NB: -1 means no +lazy, 0 means use the default batch size. + * Flag set when this fetch path needs to be a query join. */ - private int lazyFetchBatch = -1; - - private FetchConfig fetchConfig; + private boolean markForQueryJoin; private boolean cache; private boolean readOnly; - /** - * Note this SHOULD be a LinkedHashSet to preserve order of the properties. This is to make using - * SqlSelect easier with predictable property/column ordering. - */ - private final LinkedHashSet included; - /** * Included bean joins. */ @@ -70,8 +62,7 @@ public class OrmQueryProperties implements Serializable { private List secondaryChildren; /** - * OrderBy properties that where on the main query but moved here as they relate to this (query - * join). + * OrderBy properties that where on the main query but moved here as they relate to this (query join). */ @SuppressWarnings("rawtypes") private OrderBy orderBy; @@ -98,6 +89,7 @@ public class OrmQueryProperties implements Serializable { this.rawProperties = null; this.trimmedProperties = null; this.included = null; + this.fetchConfig = DEFAULT_FETCH; } public OrmQueryProperties(String path, String rawProperties) { @@ -113,16 +105,12 @@ public class OrmQueryProperties implements Serializable { this.rawProperties = rawProperties; this.trimmedProperties = response.properties; this.included = response.included; - this.lazyFetchBatch = response.lazyFetchBatch; - this.queryFetchBatch = response.queryFetchBatch; this.cache = response.cache; this.readOnly = response.readOnly; - if (fetchConfig != null) { this.fetchConfig = fetchConfig; - lazyFetchBatch = fetchConfig.getLazyBatchSize(); - queryFetchBatch = fetchConfig.getQueryBatchSize(); - queryFetchAll = fetchConfig.isQueryAll(); + } else { + this.fetchConfig = response.fetchConfig; } } @@ -137,11 +125,9 @@ public class OrmQueryProperties implements Serializable { this.included = parsedProperties; this.rawProperties = join(parsedProperties); this.trimmedProperties = rawProperties; - this.lazyFetchBatch = -1; - this.queryFetchBatch = -1; this.cache = false; this.readOnly = false; - this.queryFetchAll = false; + this.fetchConfig = DEFAULT_FETCH; } /** @@ -172,9 +158,7 @@ public class OrmQueryProperties implements Serializable { this.trimmedProperties = source.trimmedProperties; this.cache = source.cache; this.readOnly = source.readOnly; - this.queryFetchAll = source.queryFetchAll; - this.queryFetchBatch = source.queryFetchBatch; - this.lazyFetchBatch = source.lazyFetchBatch; + this.fetchConfig = source.fetchConfig; this.filterMany = source.filterMany; this.included = (source.included == null) ? null : new LinkedHashSet(source.included); if (includedBeanJoin != null) { @@ -216,9 +200,7 @@ public class OrmQueryProperties implements Serializable { ExpressionFactory filterEf = queryEf.createExpressionFactory();// exprPath); filterMany = new FilterExpressionList(exprPath, filterEf, rootQuery); // by default we need to make this a 'query join' now - queryFetchAll = true; - queryFetchBatch = 100; - lazyFetchBatch = 100; + markForQueryJoin = true; } return filterMany; } @@ -409,9 +391,11 @@ public class OrmQueryProperties implements Serializable { return included == null || included.contains(propName); } - public void setQueryFetch(int batch, boolean queryFetchAll) { - this.queryFetchBatch = batch; - this.queryFetchAll = queryFetchAll; + /** + * Mark this path as needing to be a query join. + */ + public void markForQueryJoin() { + markForQueryJoin = true; } public boolean isFetchJoin() { @@ -419,23 +403,23 @@ public class OrmQueryProperties implements Serializable { } public boolean isQueryFetch() { - return queryFetchBatch > -1; + return markForQueryJoin || getQueryFetchBatch() > -1; } public int getQueryFetchBatch() { - return queryFetchBatch; + return fetchConfig.getQueryBatchSize(); } public boolean isQueryFetchAll() { - return queryFetchAll; + return fetchConfig.isQueryAll(); } public boolean isLazyFetch() { - return lazyFetchBatch > -1; + return getLazyFetchBatch() > -1; } public int getLazyFetchBatch() { - return lazyFetchBatch; + return fetchConfig.getLazyBatchSize(); } public boolean isReadOnly() { @@ -474,9 +458,7 @@ public class OrmQueryProperties implements Serializable { if (!Same.sameByNull(filterMany, p2.filterMany)) return false; if (filterMany != null && !filterMany.isSameByPlan(p2.filterMany)) return false; - return lazyFetchBatch == p2.lazyFetchBatch - && queryFetchBatch == p2.queryFetchBatch - && queryFetchAll == p2.queryFetchAll; + return fetchConfig.equals(p2.fetchConfig); } /** @@ -492,9 +474,7 @@ public class OrmQueryProperties implements Serializable { if (filterMany != null) { filterMany.queryPlanHash(builder); } - builder.add(lazyFetchBatch); - builder.add(queryFetchBatch); - builder.add(queryFetchAll); + builder.add(fetchConfig.hashCode()); } } diff --git a/src/main/java/com/avaje/ebeaninternal/server/querydefn/OrmQueryPropertiesParser.java b/src/main/java/com/avaje/ebeaninternal/server/querydefn/OrmQueryPropertiesParser.java index fce8b056d..3027dc20b 100644 --- a/src/main/java/com/avaje/ebeaninternal/server/querydefn/OrmQueryPropertiesParser.java +++ b/src/main/java/com/avaje/ebeaninternal/server/querydefn/OrmQueryPropertiesParser.java @@ -1,5 +1,6 @@ package com.avaje.ebeaninternal.server.querydefn; +import com.avaje.ebean.FetchConfig; import com.avaje.ebeaninternal.server.lib.util.StringHelper; import java.util.LinkedHashSet; @@ -18,25 +19,26 @@ public class OrmQueryPropertiesParser { final boolean readOnly; final boolean cache; - final int queryFetchBatch; - final int lazyFetchBatch; + final FetchConfig fetchConfig; final String properties; final LinkedHashSet included; public Response(boolean readOnly, boolean cache, int queryFetchBatch, int lazyFetchBatch, String properties, LinkedHashSet included) { this.readOnly = readOnly; this.cache = cache; - this.queryFetchBatch = queryFetchBatch; - this.lazyFetchBatch = lazyFetchBatch; this.properties = properties; this.included = included; + if (lazyFetchBatch > -1 || queryFetchBatch > -1) { + this.fetchConfig = new FetchConfig().lazy(lazyFetchBatch).query(queryFetchBatch); + } else { + this.fetchConfig = OrmQueryProperties.DEFAULT_FETCH; + } } public Response() { this.readOnly = false; this.cache = false; - this.queryFetchBatch = -1; - this.lazyFetchBatch = -1; + this.fetchConfig = OrmQueryProperties.DEFAULT_FETCH; this.properties = ""; this.included = null; } diff --git a/src/test/java/com/avaje/ebean/FetchConfigTest.java b/src/test/java/com/avaje/ebean/FetchConfigTest.java new file mode 100644 index 000000000..071f0a43f --- /dev/null +++ b/src/test/java/com/avaje/ebean/FetchConfigTest.java @@ -0,0 +1,168 @@ +package com.avaje.ebean; + +import org.junit.Test; + +import static org.assertj.core.api.Assertions.assertThat; + +public class FetchConfigTest { + + @Test + public void testLazy() throws Exception { + + FetchConfig config = new FetchConfig().lazy(); + + assertThat(config.getLazyBatchSize()).isEqualTo(0); + assertThat(config.getQueryBatchSize()).isEqualTo(-1); + assertThat(config.isQueryAll()).isEqualTo(false); + } + + @Test + public void testLazy_withParameter() throws Exception { + + FetchConfig config = new FetchConfig().lazy(50); + + assertThat(config.getLazyBatchSize()).isEqualTo(50); + assertThat(config.getQueryBatchSize()).isEqualTo(-1); + assertThat(config.isQueryAll()).isEqualTo(false); + } + + @Test + public void testQuery() throws Exception { + + FetchConfig config = new FetchConfig().query(); + + assertThat(config.getLazyBatchSize()).isEqualTo(-1); + assertThat(config.getQueryBatchSize()).isEqualTo(0); + assertThat(config.isQueryAll()).isEqualTo(true); + } + + @Test + public void testQuery_withParameter() throws Exception { + + FetchConfig config = new FetchConfig().query(50); + + assertThat(config.getLazyBatchSize()).isEqualTo(-1); + assertThat(config.getQueryBatchSize()).isEqualTo(50); + assertThat(config.isQueryAll()).isEqualTo(true); + } + + @Test + public void testQueryFirst() throws Exception { + + FetchConfig config = new FetchConfig().queryFirst(50); + + assertThat(config.getLazyBatchSize()).isEqualTo(-1); + assertThat(config.getQueryBatchSize()).isEqualTo(50); + assertThat(config.isQueryAll()).isEqualTo(false); + } + + @Test + public void testQueryAndLazy_withParameters() throws Exception { + + FetchConfig config = new FetchConfig().query(50).lazy(10); + + assertThat(config.getLazyBatchSize()).isEqualTo(10); + assertThat(config.getQueryBatchSize()).isEqualTo(50); + assertThat(config.isQueryAll()).isEqualTo(false); + } + + @Test + public void testQueryAndLazy() throws Exception { + + FetchConfig config = new FetchConfig().query(50).lazy(); + + assertThat(config.getLazyBatchSize()).isEqualTo(0); + assertThat(config.getQueryBatchSize()).isEqualTo(50); + assertThat(config.isQueryAll()).isEqualTo(false); + } + + + @Test + public void testEquals_when_noOptions() throws Exception { + + assertSame(new FetchConfig(), new FetchConfig()); + } + + @Test + public void testEquals_when_query_50_lazy_40() throws Exception { + + assertSame(new FetchConfig().query(50).lazy(40), new FetchConfig().query(50).lazy(40)); + } + + @Test + public void testEquals_when_query_50_lazy() throws Exception { + + assertSame(new FetchConfig().query(50).lazy(), new FetchConfig().query(50).lazy()); + } + + @Test + public void testEquals_when_query_50() throws Exception { + + assertSame(new FetchConfig().query(50), new FetchConfig().query(50)); + } + + @Test + public void testEquals_when_queryFirst_50_lazy_40() throws Exception { + + assertSame(new FetchConfig().queryFirst(50).lazy(40), new FetchConfig().queryFirst(50).lazy(40)); + } + + @Test + public void testEquals_when_queryFirst_50_lazy() throws Exception { + + assertSame(new FetchConfig().queryFirst(50).lazy(), new FetchConfig().queryFirst(50).lazy()); + } + + @Test + public void testEquals_when_queryFirst_50() throws Exception { + + assertSame(new FetchConfig().queryFirst(50), new FetchConfig().queryFirst(50)); + } + + @Test + public void testNotEquals_when_query_50() throws Exception { + + assertDifferent(new FetchConfig().query(50), new FetchConfig().query(40)); + } + + @Test + public void testNotEquals_when_query_50_lazy() throws Exception { + + assertDifferent(new FetchConfig().query(50), new FetchConfig().query(50).lazy()); + } + + @Test + public void testNotEquals_when_query_50_lazy_40() throws Exception { + + assertDifferent(new FetchConfig().query(50), new FetchConfig().query(50).lazy(40)); + } + + @Test + public void testNotEquals_when_queryFirst_50() throws Exception { + + assertDifferent(new FetchConfig().queryFirst(50), new FetchConfig().queryFirst(40)); + } + + @Test + public void testNotEquals_when_queryFirst_50_lazy() throws Exception { + + assertDifferent(new FetchConfig().queryFirst(50), new FetchConfig().queryFirst(50).lazy()); + } + + @Test + public void testNotEquals_when_queryFirst_50_lazy_40() throws Exception { + + assertDifferent(new FetchConfig().queryFirst(50), new FetchConfig().queryFirst(50).lazy(40)); + } + + void assertDifferent(FetchConfig v1, FetchConfig v2) { + assertThat(v1).isNotEqualTo(v2); + assertThat(v1.hashCode()).isNotEqualTo(v2.hashCode()); + } + + + void assertSame(FetchConfig v1, FetchConfig v2) { + assertThat(v1).isEqualTo(v2); + assertThat(v1.hashCode()).isEqualTo(v2.hashCode()); + } +} \ No newline at end of file diff --git a/src/test/java/com/avaje/ebeaninternal/server/querydefn/OrmQueryDetailTest.java b/src/test/java/com/avaje/ebeaninternal/server/querydefn/OrmQueryDetailTest.java index 31c3dac5a..55c7bfd98 100644 --- a/src/test/java/com/avaje/ebeaninternal/server/querydefn/OrmQueryDetailTest.java +++ b/src/test/java/com/avaje/ebeaninternal/server/querydefn/OrmQueryDetailTest.java @@ -1,5 +1,8 @@ package com.avaje.ebeaninternal.server.querydefn; +import com.avaje.ebean.BaseTestCase; +import com.avaje.ebeaninternal.server.deploy.BeanDescriptor; +import com.avaje.tests.model.basic.Order; import org.junit.Test; import static org.assertj.core.api.Assertions.assertThat; @@ -7,7 +10,7 @@ import static org.junit.Assert.assertFalse; import static org.junit.Assert.assertNull; import static org.junit.Assert.assertTrue; -public class OrmQueryDetailTest { +public class OrmQueryDetailTest extends BaseTestCase { OrmQueryDetail parse(String query) { return new OrmQueryDetailParser(query).parse(); @@ -115,4 +118,56 @@ public class OrmQueryDetailTest { assertThat(detail.getFetchPaths()).containsExactly("details", "customer", "details.product"); } + @Test + public void markQueryJoins_when_allowOne_expect_stillFetchJoin() { + + OrmQueryDetail detail = new OrmQueryDetail(); + detail.fetch("details", null, null); + + detail.markQueryJoins(orderDesc(), null, true); + + assertThat(detail.getChunk("details", false).isQueryFetch()).isFalse(); + } + + @Test + public void markQueryJoins_when_allowNone_expect_queryJoin() { + + OrmQueryDetail detail = new OrmQueryDetail(); + detail.fetch("details", null, null); + + detail.markQueryJoins(orderDesc(), null, false); + + assertThat(detail.getChunk("details", false).isQueryFetch()).isTrue(); + } + + @Test + public void markQueryJoins_when_allowOneButSecond_expect_queryJoin() { + + OrmQueryDetail detail = new OrmQueryDetail(); + detail.fetch("details", null, null); + detail.fetch("customer.contacts", null, null); + + detail.markQueryJoins(orderDesc(), null, true); + + assertThat(detail.getChunk("details", false).isQueryFetch()).isFalse(); + assertThat(detail.getChunk("customer.contacts", false).isQueryFetch()).isTrue(); + } + + @Test + public void markQueryJoins_when_allowNone_expect_bothQueryJoin() { + + OrmQueryDetail detail = new OrmQueryDetail(); + detail.fetch("details", null, null); + detail.fetch("customer.contacts", null, null); + + detail.markQueryJoins(orderDesc(), null, false); + + assertThat(detail.getChunk("details", false).isQueryFetch()).isTrue(); + assertThat(detail.getChunk("customer.contacts", false).isQueryFetch()).isTrue(); + } + + BeanDescriptor orderDesc() { + return getBeanDescriptor(Order.class); + } + } \ No newline at end of file diff --git a/src/test/java/com/avaje/ebeaninternal/server/querydefn/OrmQueryPropertiesParserTest.java b/src/test/java/com/avaje/ebeaninternal/server/querydefn/OrmQueryPropertiesParserTest.java index ab519e1bb..fbc800db3 100644 --- a/src/test/java/com/avaje/ebeaninternal/server/querydefn/OrmQueryPropertiesParserTest.java +++ b/src/test/java/com/avaje/ebeaninternal/server/querydefn/OrmQueryPropertiesParserTest.java @@ -74,7 +74,7 @@ public class OrmQueryPropertiesParserTest { public void when_hasLazy() throws Exception { OrmQueryPropertiesParser.Response res = OrmQueryPropertiesParser.parse("+lazy"); - assertThat(res.lazyFetchBatch).isEqualTo(0); + assertThat(res.fetchConfig.getLazyBatchSize()).isEqualTo(0); assertThat(res.included).isNull(); } @@ -82,7 +82,7 @@ public class OrmQueryPropertiesParserTest { public void when_hasLazyValue() throws Exception { OrmQueryPropertiesParser.Response res = OrmQueryPropertiesParser.parse("+lazy(20)"); - assertThat(res.lazyFetchBatch).isEqualTo(20); + assertThat(res.fetchConfig.getLazyBatchSize()).isEqualTo(20); assertThat(res.included).isNull(); } @@ -90,7 +90,7 @@ public class OrmQueryPropertiesParserTest { public void when_hasLazyValue_last() throws Exception { OrmQueryPropertiesParser.Response res = OrmQueryPropertiesParser.parse("name,+lazy(20)"); - assertThat(res.lazyFetchBatch).isEqualTo(20); + assertThat(res.fetchConfig.getLazyBatchSize()).isEqualTo(20); assertThat(res.included).containsExactly("name"); } @@ -98,7 +98,7 @@ public class OrmQueryPropertiesParserTest { public void when_hasLazyValue_first() throws Exception { OrmQueryPropertiesParser.Response res = OrmQueryPropertiesParser.parse("+lazy(20),id,name"); - assertThat(res.lazyFetchBatch).isEqualTo(20); + assertThat(res.fetchConfig.getLazyBatchSize()).isEqualTo(20); assertThat(res.included).containsExactly("id", "name"); } @@ -106,17 +106,16 @@ public class OrmQueryPropertiesParserTest { public void when_allProperties() throws Exception { OrmQueryPropertiesParser.Response res = OrmQueryPropertiesParser.parse("+query(4),+lazy(5)"); - assertThat(res.lazyFetchBatch).isEqualTo(5); + assertThat(res.fetchConfig.getLazyBatchSize()).isEqualTo(5); assertThat(res.included).isNull(); } - @Test public void when_everything_set() throws Exception { OrmQueryPropertiesParser.Response res = OrmQueryPropertiesParser.parse("id, name +readonly +lazy(20) +query(30) +cache"); - assertThat(res.lazyFetchBatch).isEqualTo(20); - assertThat(res.queryFetchBatch).isEqualTo(30); + assertThat(res.fetchConfig.getLazyBatchSize()).isEqualTo(20); + assertThat(res.fetchConfig.getQueryBatchSize()).isEqualTo(30); assertThat(res.readOnly).isTrue(); assertThat(res.cache).isTrue(); assertThat(res.included).containsExactly("id", "name"); @@ -125,8 +124,8 @@ public class OrmQueryPropertiesParserTest { private void assertAllDefaults(OrmQueryPropertiesParser.Response res) { assertThat(res.cache).isFalse(); assertThat(res.readOnly).isFalse(); - assertThat(res.lazyFetchBatch).isEqualTo(-1); - assertThat(res.queryFetchBatch).isEqualTo(-1); + assertThat(res.fetchConfig.getLazyBatchSize()).isEqualTo(-1); + assertThat(res.fetchConfig.getQueryBatchSize()).isEqualTo(-1); assertThat(res.included).isNull(); } } \ No newline at end of file