m = new HashMap<>();
for (STreePropertyAssocMany many : desc.propsMany()) {
@@ -173,293 +159,6 @@ class SqlTreeNodeBean implements SqlTreeNode {
}
}
- /**
- * Load that takes into account inheritance.
- */
- private final class LoadInherit extends Load {
-
- private LoadInherit(DbReadContext ctx, EntityBean parentBean) {
- super(ctx, parentBean);
- }
-
- @Override
- void initBeanType() throws SQLException {
- InheritInfo localInfo = readId ? inheritInfo.readType(ctx) : desc.inheritInfo();
- if (localInfo == null) {
- // the bean must be null
- localIdBinder = idBinder;
- localDesc = desc;
- } else {
- localBean = localInfo.createEntityBean();
- localType = localInfo.getType();
- localIdBinder = localInfo.getIdBinder();
- localDesc = localInfo.desc();
- }
- }
-
- @Override
- void loadProperties() {
- // take account of inheritance
- for (STreeProperty property : properties) {
- localDesc.inheritanceLoad(sqlBeanLoad, property, ctx);
- }
- }
- }
-
- /**
- * Load a bean instance.
- */
- class Load {
-
- final DbReadContext ctx;
- final EntityBean parentBean;
-
- Object lazyLoadParentId;
- Class> localType;
- STreeType localDesc;
- IdBinder localIdBinder;
- EntityBean localBean;
-
- Mode queryMode;
- PersistenceContext persistenceContext;
- Object id;
- EntityBean contextBean;
- SqlBeanLoad sqlBeanLoad;
- boolean lazyLoadMany;
-
- private Load(DbReadContext ctx, EntityBean parentBean) {
- this.ctx = ctx;
- this.parentBean = parentBean;
- }
-
- private void initLazyParent() throws SQLException {
- if (lazyLoadParentIdBinder != null) {
- lazyLoadParentId = lazyLoadParentIdBinder.read(ctx);
- }
- }
-
- void initBeanType() throws SQLException {
- localDesc = desc;
- localBean = desc.createEntityBean();
- localIdBinder = idBinder;
- }
-
- private void initPersistenceContext() {
- queryMode = ctx.getQueryMode();
- persistenceContext = (!readIdNormal) ? null : ctx.getPersistenceContext();
- }
-
- private void readId() throws SQLException {
- if (readId) {
- id = localIdBinder.readSet(ctx, localBean);
- if (id == null) {
- readIdNullBean();
- } else if (!temporalVersions) {
- readIdBean();
- }
- }
- }
-
- private void readIdBean() {
- // check the PersistenceContext to see if the bean already exists
- contextBean = (EntityBean) localDesc.contextPutIfAbsent(persistenceContext, id, localBean);
- if (contextBean == null) {
- // bean just added to the persistenceContext
- contextBean = localBean;
- } else {
- // bean already exists in persistenceContext
-
- if (queryMode.isLoadContextBean()) {
- // if explicitly set loadContextBean to true, then reload
- localBean = contextBean;
- } else if (!contextBean._ebean_getIntercept().isFullyLoadedBean()) {
- // reload if contextBean is partial object
- localBean = contextBean;
- // and switch to lazyLoad query mode in order not to overwrite
- // existing properties in SqlBeanLoad::load
- queryMode = Mode.LAZYLOAD_BEAN;
- } else {
- // ignore the DB data...
- localBean = null;
- }
- }
- }
-
- private void readIdNullBean() {
- // bean must be null...
- localBean = null;
- // ... but there may exist as reference bean in parent which has to be marked as deleted.
- if (parentBean != null && nodeBeanProp instanceof STreePropertyAssocOne) {
- contextBean = ((STreePropertyAssocOne)nodeBeanProp).getValueAsEntityBean(parentBean);
- if (contextBean != null) {
- desc.markAsDeleted(contextBean);
- }
- }
- }
-
- private void initSqlLoadBean() {
- ctx.setCurrentPrefix(prefix, pathMap);
- ctx.propagateState(localBean);
- sqlBeanLoad = new SqlBeanLoad(ctx, localType, localBean, queryMode);
- }
-
- void loadProperties() {
- for (STreeProperty property : properties) {
- property.load(sqlBeanLoad);
- }
- }
-
- private void loadChildren() throws SQLException {
- if (localBean == null && queryMode == Mode.LAZYLOAD_MANY) {
- // batch lazy load many into existing contextBean
- localBean = contextBean;
- lazyLoadMany = true;
- }
- for (SqlTreeNode child : children) {
- child.load(ctx, localBean, contextBean);
- }
- }
-
- private boolean isLazyLoadManyRoot() {
- return queryMode == Mode.LAZYLOAD_MANY && isRoot();
- }
-
- private EntityBean getContextBean() {
- return contextBean;
- }
-
- private void postLoad() {
- if (!lazyLoadMany && localBean != null) {
- ctx.setCurrentPrefix(prefix, pathMap);
- if (readIdNormal) {
- createListProxies();
- }
- if (temporalMode == SpiQuery.TemporalMode.DRAFT) {
- localDesc.setDraft(localBean);
- }
- localDesc.postLoad(localBean);
-
- EntityBeanIntercept ebi = localBean._ebean_getIntercept();
- ebi.setPersistenceContext(persistenceContext);
- if (Mode.LAZYLOAD_BEAN == queryMode) {
- // Lazy Load does not reset the dirty state
- ebi.setLoadedLazy();
- } else if (readId) {
- // normal bean loading
- ebi.setLoaded();
- }
-
- if (disableLazyLoad) {
- // bean does not have an Id or is SqlSelect based
- ebi.setDisableLazyLoad(true);
- } else if (partialObject) {
- if (readId) {
- // register for lazy loading
- ctx.register(null, ebi);
- }
- } else {
- ebi.setFullyLoadedBean(true);
- }
-
- if (ctx.isAutoTuneProfiling() && !disableLazyLoad) {
- // collect autoTune profiling for this bean...
- ctx.profileBean(ebi, prefix);
- }
- }
- }
-
- /**
- * Create lazy loading proxies for the Many's except for the one that is
- * included in the actual query.
- */
- private void createListProxies() {
- STreePropertyAssocMany fetchedMany = ctx.getManyProperty();
- boolean forceNewReference = queryMode == Mode.REFRESH_BEAN;
- for (STreePropertyAssocMany many : localDesc.propsMany()) {
- if (many != fetchedMany) {
- // create a proxy for the many (deferred fetching)
- BeanCollection> ref = many.createReference(localBean, forceNewReference);
- if (ref != null) {
- if (disableLazyLoad) {
- ref.setDisableLazyLoad(true);
- }
- if (!ref.isRegisteredWithLoadContext()) {
- ctx.register(many.asMany(), ref);
- }
- }
- }
- }
- }
-
- private void setBeanToParent() {
- if (parentBean != null) {
- // set this back to the parentBean
- nodeBeanProp.setValue(parentBean, contextBean);
- }
- }
-
- private EntityBean complete() {
- if (!readIdNormal) {
- // a bean with no Id (never found in context)
- if (lazyLoadParentId != null) {
- ctx.setLazyLoadedChildBean(localBean, lazyLoadParentId);
- }
- return localBean;
- } else {
- if (lazyLoadParentId != null) {
- ctx.setLazyLoadedChildBean(contextBean, lazyLoadParentId);
- }
- return contextBean;
- }
- }
-
- private void initialise() throws SQLException {
- initLazyParent();
- initBeanType();
- initPersistenceContext();
- readId();
- initSqlLoadBean();
- loadProperties();
- loadChildren();
- }
-
- /**
- * Perform the load returning the loaded bean.
- */
- final EntityBean perform() throws SQLException {
- initialise();
- if (isLazyLoadManyRoot()) {
- return getContextBean();
- }
- postLoad();
- setBeanToParent();
- return complete();
- }
-
- /**
- * Return true if this bean was already in the context. If already in the
- * context we need to check if it is already contained in the collection.
- */
- final boolean isContextBean() {
- return localBean == null;
- }
- }
-
- /**
- * read the properties from the resultSet.
- */
- @Override
- public EntityBean load(DbReadContext ctx, EntityBean parentBean, EntityBean contextParent) throws SQLException {
- return createLoad(ctx, parentBean).perform();
- }
-
- /**
- * Create the loader with or without inheritance.
- */
- final Load createLoad(DbReadContext ctx, EntityBean parentBean) {
- return (inheritInfo != null) ? new LoadInherit(ctx, parentBean) : new Load(ctx, parentBean);
- }
-
@Override
public final void appendGroupBy(DbSqlContext ctx, boolean subQuery) {
ctx.pushJoin(prefix);
diff --git a/ebean-core/src/main/java/io/ebeaninternal/server/query/SqlTreeNodeExtraJoin.java b/ebean-core/src/main/java/io/ebeaninternal/server/query/SqlTreeNodeExtraJoin.java
index e7ca5d9ab..42d2395b5 100644
--- a/ebean-core/src/main/java/io/ebeaninternal/server/query/SqlTreeNodeExtraJoin.java
+++ b/ebean-core/src/main/java/io/ebeaninternal/server/query/SqlTreeNodeExtraJoin.java
@@ -38,6 +38,11 @@ final class SqlTreeNodeExtraJoin implements SqlTreeNode {
this.manyJoin = assocBeanProperty instanceof STreePropertyAssocMany;
}
+ @Override
+ public SqlTreeLoad createLoad() {
+ return null;
+ }
+
@Override
public boolean isSingleProperty() {
return false;
@@ -73,11 +78,6 @@ final class SqlTreeNodeExtraJoin implements SqlTreeNode {
// nothing to do here
}
- @Override
- public ScalarType> getSingleAttributeReader() {
- throw new IllegalStateException("No expected");
- }
-
/**
* Return true if the extra join is a many join.
*
@@ -184,14 +184,6 @@ final class SqlTreeNodeExtraJoin implements SqlTreeNode {
public void appendWhere(DbSqlContext ctx) {
}
- /**
- * Does nothing.
- */
- @Override
- public EntityBean load(DbReadContext ctx, EntityBean localBean, EntityBean parentBean) {
- return null;
- }
-
@Override
public boolean hasMany() {
return manyJoin;
diff --git a/ebean-core/src/main/java/io/ebeaninternal/server/query/SqlTreeNodeFormulaWhereJoin.java b/ebean-core/src/main/java/io/ebeaninternal/server/query/SqlTreeNodeFormulaWhereJoin.java
index 06a71133a..502c28a6d 100644
--- a/ebean-core/src/main/java/io/ebeaninternal/server/query/SqlTreeNodeFormulaWhereJoin.java
+++ b/ebean-core/src/main/java/io/ebeaninternal/server/query/SqlTreeNodeFormulaWhereJoin.java
@@ -33,13 +33,13 @@ final class SqlTreeNodeFormulaWhereJoin implements SqlTreeNode {
}
@Override
- public boolean isSingleProperty() {
- return true;
+ public SqlTreeLoad createLoad() {
+ return null;
}
@Override
- public ScalarType> getSingleAttributeReader() {
- throw new IllegalStateException("No expected");
+ public boolean isSingleProperty() {
+ return true;
}
@Override
@@ -98,12 +98,6 @@ final class SqlTreeNodeFormulaWhereJoin implements SqlTreeNode {
// nothing to do here
}
- @Override
- public EntityBean load(DbReadContext ctx, EntityBean localBean, EntityBean parentBean) {
- // nothing to do here
- return null;
- }
-
@Override
public boolean hasMany() {
return true;
diff --git a/ebean-core/src/main/java/io/ebeaninternal/server/query/SqlTreeNodeManyRoot.java b/ebean-core/src/main/java/io/ebeaninternal/server/query/SqlTreeNodeManyRoot.java
index c030e96bc..a8b323533 100644
--- a/ebean-core/src/main/java/io/ebeaninternal/server/query/SqlTreeNodeManyRoot.java
+++ b/ebean-core/src/main/java/io/ebeaninternal/server/query/SqlTreeNodeManyRoot.java
@@ -1,16 +1,13 @@
package io.ebeaninternal.server.query;
-import io.ebean.bean.EntityBean;
import io.ebeaninternal.api.SpiQuery;
-import io.ebeaninternal.server.deploy.DbReadContext;
import io.ebeaninternal.server.deploy.DbSqlContext;
-import java.sql.SQLException;
import java.util.List;
final class SqlTreeNodeManyRoot extends SqlTreeNodeBean {
- private final STreePropertyAssocMany manyProp;
+ final STreePropertyAssocMany manyProp;
SqlTreeNodeManyRoot(String prefix, STreePropertyAssocMany prop, SqlTreeProperties props, List myList,
boolean withId, SpiQuery.TemporalMode temporalMode, boolean disableLazyLoad) {
@@ -19,22 +16,13 @@ final class SqlTreeNodeManyRoot extends SqlTreeNodeBean {
}
@Override
- public boolean hasMany() {
- return true;
+ public SqlTreeLoad createLoad() {
+ return new SqlTreeLoadManyRoot(this);
}
@Override
- public EntityBean load(DbReadContext cquery, EntityBean parentBean, EntityBean contextParent) throws SQLException {
- // pass in null for parentBean because added to a collection rather than set to the parentBean
- SqlTreeNodeBean.Load load = createLoad(cquery, null);
- EntityBean detailBean = load.perform();
- if (contextParent != null) {
- // Add to the collection and initialise collection if needed
- // A null detailBean may initialise an empty collection
- // Check for bean existing in collection based on load.isContextBean()
- manyProp.addBeanToCollectionWithCreate(contextParent, detailBean, load.isContextBean());
- }
- return detailBean;
+ public boolean hasMany() {
+ return true;
}
/**
diff --git a/ebean-core/src/main/java/io/ebeaninternal/server/query/SqlTreeNodeManyWhereJoin.java b/ebean-core/src/main/java/io/ebeaninternal/server/query/SqlTreeNodeManyWhereJoin.java
index 73c7a18b2..cb2ba54e7 100644
--- a/ebean-core/src/main/java/io/ebeaninternal/server/query/SqlTreeNodeManyWhereJoin.java
+++ b/ebean-core/src/main/java/io/ebeaninternal/server/query/SqlTreeNodeManyWhereJoin.java
@@ -1,10 +1,7 @@
package io.ebeaninternal.server.query;
-import io.ebean.bean.EntityBean;
-import io.ebean.core.type.ScalarType;
import io.ebean.util.SplitName;
import io.ebeaninternal.api.SpiQuery;
-import io.ebeaninternal.server.deploy.DbReadContext;
import io.ebeaninternal.server.deploy.DbSqlContext;
import io.ebeaninternal.server.deploy.TableJoin;
@@ -37,13 +34,13 @@ final class SqlTreeNodeManyWhereJoin implements SqlTreeNode {
}
@Override
- public boolean isSingleProperty() {
- return false;
+ public SqlTreeLoad createLoad() {
+ return null;
}
@Override
- public ScalarType> getSingleAttributeReader() {
- throw new IllegalStateException("No expected");
+ public boolean isSingleProperty() {
+ return false;
}
@Override
@@ -132,12 +129,6 @@ final class SqlTreeNodeManyWhereJoin implements SqlTreeNode {
// nothing to do here
}
- @Override
- public EntityBean load(DbReadContext ctx, EntityBean localBean, EntityBean parentBean) {
- // nothing to do here
- return null;
- }
-
@Override
public boolean hasMany() {
return true;
diff --git a/ebean-core/src/main/java/io/ebeaninternal/server/query/SqlTreeNodeRoot.java b/ebean-core/src/main/java/io/ebeaninternal/server/query/SqlTreeNodeRoot.java
index a58c51cc5..c25024624 100644
--- a/ebean-core/src/main/java/io/ebeaninternal/server/query/SqlTreeNodeRoot.java
+++ b/ebean-core/src/main/java/io/ebeaninternal/server/query/SqlTreeNodeRoot.java
@@ -1,21 +1,16 @@
package io.ebeaninternal.server.query;
-import io.ebean.Version;
-import io.ebean.bean.EntityBean;
import io.ebeaninternal.api.SpiQuery;
-import io.ebeaninternal.server.deploy.DbReadContext;
import io.ebeaninternal.server.deploy.DbSqlContext;
import io.ebeaninternal.server.deploy.TableJoin;
-import java.sql.SQLException;
-import java.sql.Timestamp;
import java.util.List;
import java.util.Set;
/**
* Represents the root node of the Sql Tree.
*/
-final class SqlTreeNodeRoot extends SqlTreeNodeBean implements SqlTreeRoot {
+final class SqlTreeNodeRoot extends SqlTreeNodeBean {
private final TableJoin includeJoin;
private final boolean sqlDistinct;
@@ -34,27 +29,8 @@ final class SqlTreeNodeRoot extends SqlTreeNodeBean implements SqlTreeRoot {
}
@Override
- protected boolean isRoot() {
- return true;
- }
-
- @Override
- public EntityBean load(DbReadContext ctx) throws SQLException {
- return load(ctx, null, null);
- }
-
- /**
- * Read the version bean.
- */
- @Override
- @SuppressWarnings("unchecked")
- public Version loadVersion(DbReadContext ctx) throws SQLException {
- // read the sys period lower and upper bounds
- // these are always the first 2 columns in the resultSet
- Timestamp start = ctx.getDataReader().getTimestamp();
- Timestamp end = ctx.getDataReader().getTimestamp();
- T bean = (T) load(ctx, null, null);
- return new Version<>(bean, start, end);
+ public SqlTreeLoad createLoad() {
+ return new SqlTreeLoadRoot(this);
}
@Override
diff --git a/ebean-core/src/main/java/io/ebeaninternal/server/query/SqlTreePlan.java b/ebean-core/src/main/java/io/ebeaninternal/server/query/SqlTreePlan.java
new file mode 100644
index 000000000..7a0e929ef
--- /dev/null
+++ b/ebean-core/src/main/java/io/ebeaninternal/server/query/SqlTreePlan.java
@@ -0,0 +1,41 @@
+package io.ebeaninternal.server.query;
+
+import java.util.Set;
+
+final class SqlTreePlan {
+
+ private final SqlTreeLoad rootNode;
+ private final STreePropertyAssocMany manyProperty;
+ private final STreeProperty[] encryptedProps;
+ private final Set dependentTables;
+
+ SqlTreePlan(SqlTreeLoad rootNode, STreePropertyAssocMany manyProperty, STreeProperty[] encryptedProps, Set dependentTables) {
+ this.rootNode = rootNode;
+ this.manyProperty = manyProperty;
+ this.encryptedProps = encryptedProps;
+ this.dependentTables = dependentTables;
+ }
+
+ SqlTreeRoot getRootNode() {
+ return (SqlTreeRoot)rootNode;
+ }
+
+ /**
+ * Return the property that is associated with the many. There can only be one
+ * per SqlSelect. This can be null.
+ */
+ STreePropertyAssocMany getManyProperty() {
+ return manyProperty;
+ }
+
+ STreeProperty[] getEncryptedProps() {
+ return encryptedProps;
+ }
+
+ /**
+ * Return the tables that are joined in this query.
+ */
+ Set dependentTables() {
+ return dependentTables;
+ }
+}
diff --git a/ebean-externalmapping-xml/pom.xml b/ebean-externalmapping-xml/pom.xml
index 94047ec2e..f7568dc73 100644
--- a/ebean-externalmapping-xml/pom.xml
+++ b/ebean-externalmapping-xml/pom.xml
@@ -89,7 +89,7 @@
- io.ebean.tile:enhancement:12.11.3
+ io.ebean.tile:enhancement:12.14.1
io.avaje.tile:moditech-module:1.0
diff --git a/ebean-kotlin/pom.xml b/ebean-kotlin/pom.xml
index 35923973c..8d8a3d3b9 100644
--- a/ebean-kotlin/pom.xml
+++ b/ebean-kotlin/pom.xml
@@ -14,7 +14,7 @@
1.8
1.8
- 12.13.0
+ 12.14.1
1.6.0
diff --git a/ebean-postgis/pom.xml b/ebean-postgis/pom.xml
index ac4553b77..caa1ccf81 100644
--- a/ebean-postgis/pom.xml
+++ b/ebean-postgis/pom.xml
@@ -105,7 +105,7 @@
true
- io.ebean.tile:enhancement:12.11.3
+ io.ebean.tile:enhancement:12.14.1
io.avaje.tile:moditech-module:1.0
diff --git a/ebean-querybean/pom.xml b/ebean-querybean/pom.xml
index 6ecbfafad..210e2249e 100644
--- a/ebean-querybean/pom.xml
+++ b/ebean-querybean/pom.xml
@@ -100,7 +100,7 @@
true
- io.ebean.tile:enhancement:12.11.3
+ io.ebean.tile:enhancement:12.14.1
io.avaje.tile:moditech-module:1.0
diff --git a/ebean-redis/pom.xml b/ebean-redis/pom.xml
index e811c97ad..f33064c74 100644
--- a/ebean-redis/pom.xml
+++ b/ebean-redis/pom.xml
@@ -80,7 +80,7 @@
true
- io.ebean.tile:enhancement:12.11.3
+ io.ebean.tile:enhancement:12.14.1
io.avaje.tile:moditech-module:1.0
diff --git a/ebean-test/pom.xml b/ebean-test/pom.xml
index e5c80afb8..2d210584d 100644
--- a/ebean-test/pom.xml
+++ b/ebean-test/pom.xml
@@ -249,7 +249,7 @@
true
- io.ebean.tile:enhancement:12.11.3
+ io.ebean.tile:enhancement:12.14.1
io.avaje.tile:moditech-module:1.0
diff --git a/ebean-test/src/test/java/io/ebeaninternal/server/core/DefaultServer_getReferenceTest.java b/ebean-test/src/test/java/io/ebeaninternal/server/core/DefaultServer_getReferenceTest.java
index bbf2786b4..e638d9d00 100644
--- a/ebean-test/src/test/java/io/ebeaninternal/server/core/DefaultServer_getReferenceTest.java
+++ b/ebean-test/src/test/java/io/ebeaninternal/server/core/DefaultServer_getReferenceTest.java
@@ -24,8 +24,8 @@ public class DefaultServer_getReferenceTest extends BaseTestCase {
ResetBasicData.reset();
DB.execute(() -> {
- Customer loaded = DB.find(Customer.class, 1);
- Customer reference = DB.reference(Customer.class, 1);
+ Customer loaded = DB.find(Customer.class).where().eq("name", "Rob").findOne();
+ Customer reference = DB.reference(Customer.class, loaded.getId());
assertThat(loaded).isSameAs(reference);
});
}
diff --git a/ebean-test/src/test/java/io/ebeaninternal/server/deploy/BeanPropertyAssocManyTest.java b/ebean-test/src/test/java/io/ebeaninternal/server/deploy/BeanPropertyAssocManyTest.java
index c63966f21..eadc01968 100644
--- a/ebean-test/src/test/java/io/ebeaninternal/server/deploy/BeanPropertyAssocManyTest.java
+++ b/ebean-test/src/test/java/io/ebeaninternal/server/deploy/BeanPropertyAssocManyTest.java
@@ -1,6 +1,7 @@
package io.ebeaninternal.server.deploy;
import io.ebean.BaseTestCase;
+import io.ebean.DB;
import io.ebean.bean.BeanCollection;
import io.ebean.bean.EntityBean;
import io.ebean.common.BeanList;
@@ -66,11 +67,13 @@ public class BeanPropertyAssocManyTest extends BaseTestCase {
ResetBasicData.reset();
- List