diff --git a/src/main/java/io/ebeaninternal/server/query/SqlTreeNodeBean.java b/src/main/java/io/ebeaninternal/server/query/SqlTreeNodeBean.java index 10fcca6c0..7d34f44f6 100644 --- a/src/main/java/io/ebeaninternal/server/query/SqlTreeNodeBean.java +++ b/src/main/java/io/ebeaninternal/server/query/SqlTreeNodeBean.java @@ -218,28 +218,20 @@ class SqlTreeNodeBean implements SqlTreeNode { } /** - * read the properties from the resultSet. + * Load that takes into account inheritance. */ - @Override - public EntityBean load(DbReadContext ctx, EntityBean parentBean, EntityBean contextParent) throws SQLException { + private class LoadInherit extends Load { - Object lazyLoadParentId = null; - if (lazyLoadParentIdBinder != null) { - lazyLoadParentId = lazyLoadParentIdBinder.read(ctx); + LoadInherit(DbReadContext ctx, EntityBean parentBean, EntityBean contextParent) { + super(ctx, parentBean, contextParent); } - Class localType; - STreeType localDesc; - IdBinder localIdBinder; - EntityBean localBean; - - if (inheritInfo != null) { + @Override + void initBeanType() throws SQLException { InheritInfo localInfo = inheritInfo.readType(ctx); if (localInfo == null) { // the bean must be null localIdBinder = idBinder; - localBean = null; - localType = null; localDesc = desc; } else { localBean = localInfo.createEntityBean(); @@ -247,65 +239,10 @@ class SqlTreeNodeBean implements SqlTreeNode { localIdBinder = localInfo.getIdBinder(); localDesc = localInfo.desc(); } - - } else { - localType = null; - localDesc = desc; - localBean = desc.createEntityBean(); - localIdBinder = idBinder; } - Mode queryMode = ctx.getQueryMode(); - - PersistenceContext persistenceContext = (!readId || temporalVersions) ? null : ctx.getPersistenceContext(); - - // bean already existing in the persistence context - EntityBean contextBean = null; - if (readId) { - Object id = localIdBinder.readSet(ctx, localBean); - if (id == null) { - // 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); - } - } - } else if (!temporalVersions) { - // 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 (isLoadContextBeanNeeded(queryMode, contextBean)) { - // refresh it anyway (lazy loading for example) - localBean = contextBean; - } else { - // ignore the DB data... - localBean = null; - } - } - } - } - - ctx.setCurrentPrefix(prefix, pathMap); - - ctx.propagateState(localBean); - - SqlBeanLoad sqlBeanLoad = new SqlBeanLoad(ctx, localType, localBean, queryMode); - - if (inheritInfo == null) { - // normal behavior with no inheritance - for (STreeProperty property : properties) { - property.load(sqlBeanLoad); - } - - } else { + @Override + void loadProperties() { // take account of inheritance and due to subclassing approach // need to get a 'local' version of the property for (STreeProperty property : properties) { @@ -313,82 +250,220 @@ class SqlTreeNodeBean implements SqlTreeNode { localDesc.inheritanceLoad(sqlBeanLoad, property, ctx); } } + } - boolean lazyLoadMany = false; - if (localBean == null && queryMode == Mode.LAZYLOAD_MANY) { - // batch lazy load many into existing contextBean - localBean = contextBean; - lazyLoadMany = true; + /** + * Load a bean instance. + */ + private class Load { + + final DbReadContext ctx; + final EntityBean parentBean; + final EntityBean contextParent; + + Object lazyLoadParentId; + Class localType; + STreeType localDesc; + IdBinder localIdBinder; + EntityBean localBean; + + Mode queryMode; + PersistenceContext persistenceContext; + Object id; + EntityBean contextBean; + SqlBeanLoad sqlBeanLoad; + boolean lazyLoadMany; + + Load(DbReadContext ctx, EntityBean parentBean, EntityBean contextParent) { + this.ctx = ctx; + this.parentBean = parentBean; + this.contextParent = contextParent; } - // recursively continue reading... - for (SqlTreeNode aChildren : children) { - // read each child... and let them set their - // values back to this localBean - aChildren.load(ctx, localBean, contextBean); + void initLazyParent() throws SQLException { + if (lazyLoadParentIdBinder != null) { + lazyLoadParentId = lazyLoadParentIdBinder.read(ctx); + } } - if (queryMode == Mode.LAZYLOAD_MANY && isRoot()) { - return contextBean; + void initBeanType() throws SQLException { + localDesc = desc; + localBean = desc.createEntityBean(); + localIdBinder = idBinder; } - if (!lazyLoadMany && localBean != null) { - ctx.setCurrentPrefix(prefix, pathMap); - if (readId && !temporalVersions) { - createListProxies(localDesc, ctx, localBean, disableLazyLoad); - } - if (temporalMode == SpiQuery.TemporalMode.DRAFT) { - localDesc.setDraft(localBean); - } - localDesc.postLoad(localBean); + void initPersistenceContext() { + queryMode = ctx.getQueryMode(); + persistenceContext = (!readId || temporalVersions) ? null : ctx.getPersistenceContext(); + } - 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); + 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 { - ebi.setFullyLoadedBean(true); - } - - if (ctx.isAutoTuneProfiling() && !disableLazyLoad) { - // collect autoTune profiling for this bean... - ctx.profileBean(ebi, prefix); + // bean already exists in persistenceContext + if (isLoadContextBeanNeeded(queryMode, contextBean)) { + // refresh it anyway (lazy loading for example) + localBean = contextBean; + } else { + // ignore the DB data... + localBean = null; + } } } - if (parentBean != null) { - // set this back to the parentBean - nodeBeanProp.setValue(parentBean, contextBean); + 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); + } + } } - if (!readId || temporalVersions) { - // a bean with no Id (never found in context) - if (lazyLoadParentId != null) { - ctx.setLazyLoadedChildBean(localBean, lazyLoadParentId); - } - return localBean; + void initSqlLoadBean() { + ctx.setCurrentPrefix(prefix, pathMap); + ctx.propagateState(localBean); + sqlBeanLoad = new SqlBeanLoad(ctx, localType, localBean, queryMode); + } - } else { - if (lazyLoadParentId != null) { - ctx.setLazyLoadedChildBean(contextBean, lazyLoadParentId); + void loadProperties() { + for (STreeProperty property : properties) { + property.load(sqlBeanLoad); } + } + + void loadChildren() throws SQLException { + //boolean lazyLoadMany = false; + if (localBean == null && queryMode == Mode.LAZYLOAD_MANY) { + // batch lazy load many into existing contextBean + localBean = contextBean; + lazyLoadMany = true; + } + + // recursively continue reading... + for (SqlTreeNode aChildren : children) { + // read each child... and let them set their + // values back to this localBean + aChildren.load(ctx, localBean, contextBean); + } + } + + boolean isLazyLoadManyRoot() { + return queryMode == Mode.LAZYLOAD_MANY && isRoot(); + } + + EntityBean getContextBean() { return contextBean; } + + void postLoad() { + if (!lazyLoadMany && localBean != null) { + ctx.setCurrentPrefix(prefix, pathMap); + if (readId && !temporalVersions) { + createListProxies(localDesc, ctx, localBean, disableLazyLoad); + } + 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); + } + } + } + + void setBeanToParent() { + if (parentBean != null) { + // set this back to the parentBean + nodeBeanProp.setValue(parentBean, contextBean); + } + } + + EntityBean complete() { + if (!readId || temporalVersions) { + // 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; + } + } + + void initialise() throws SQLException { + initLazyParent(); + initBeanType(); + initPersistenceContext(); + readId(); + initSqlLoadBean(); + loadProperties(); + loadChildren(); + } + } + + /** + * read the properties from the resultSet. + */ + @Override + public EntityBean load(DbReadContext ctx, EntityBean parentBean, EntityBean contextParent) throws SQLException { + + Load load = (inheritInfo != null) ? new LoadInherit(ctx, parentBean, contextParent) : new Load(ctx, parentBean, contextParent); + load.initialise(); + if (load.isLazyLoadManyRoot()) { + return load.getContextBean(); + } + load.postLoad(); + load.setBeanToParent(); + return load.complete(); } /**