From 884ff1b86393b49d0d88fc95a7b80511dd9cb7c3 Mon Sep 17 00:00:00 2001 From: Pinaki Poddar Date: Tue, 25 Jul 2006 07:10:26 +0000 Subject: [PATCH] FetchPlan with recursive scheme. - modified select building and load cycles in JDBCStoreManager with FetchState traversal - loadAll(), findAll() methods reverted to their method signature with FetchConfiguration instead of FetchState - StateManager.postLoad checks for fetch group with postload set to true git-svn-id: https://svn.apache.org/repos/asf/incubator/openjpa/trunk@425312 13f79535-47bb-0310-9956-ffa450edef68 --- .../openjpa/jdbc/kernel/JDBCStoreManager.java | 74 +-- .../kernel/PagingResultObjectProvider.java | 2 +- .../abstractstore/AbstractStoreManager.java | 4 +- .../datacache/DataCacheStoreManager.java | 12 +- .../openjpa/enhance/PCDataGenerator.java | 2 +- .../org/apache/openjpa/kernel/BrokerImpl.java | 32 +- .../openjpa/kernel/DelegatingBroker.java | 4 +- .../kernel/DelegatingFetchConfiguration.java | 4 +- .../kernel/DelegatingStoreManager.java | 4 +- .../apache/openjpa/kernel/DetachManager.java | 2 +- .../openjpa/kernel/DetachedStateManager.java | 7 +- .../openjpa/kernel/FetchConfiguration.java | 3 +- .../kernel/FetchConfigurationImpl.java | 5 +- .../org/apache/openjpa/kernel/FetchState.java | 203 +++++--- .../apache/openjpa/kernel/FetchStateImpl.java | 439 ++++++++++-------- .../apache/openjpa/kernel/PNonTransState.java | 3 +- .../openjpa/kernel/StateManagerImpl.java | 43 +- .../apache/openjpa/kernel/StoreContext.java | 2 +- .../apache/openjpa/kernel/StoreManager.java | 2 +- .../openjpa/kernel/VersionAttachStrategy.java | 2 +- .../apache/openjpa/meta/ClassMetaData.java | 30 +- .../org/apache/openjpa/meta/FetchGroup.java | 378 +++++++-------- .../apache/openjpa/meta/FieldMetaData.java | 9 +- .../org/apache/openjpa/util/ImplHelper.java | 5 +- 24 files changed, 661 insertions(+), 610 deletions(-) diff --git a/openjpa-jdbc/src/main/java/org/apache/openjpa/jdbc/kernel/JDBCStoreManager.java b/openjpa-jdbc/src/main/java/org/apache/openjpa/jdbc/kernel/JDBCStoreManager.java index 3e047a87f..4f646c21b 100644 --- a/openjpa-jdbc/src/main/java/org/apache/openjpa/jdbc/kernel/JDBCStoreManager.java +++ b/openjpa-jdbc/src/main/java/org/apache/openjpa/jdbc/kernel/JDBCStoreManager.java @@ -441,10 +441,7 @@ public class JDBCStoreManager public boolean load(OpenJPAStateManager sm, BitSet fields, FetchState fetchState, int lockLevel, Object context) { - JDBCFetchState jfetchState = (fetchState == null) ? (JDBCFetchState) getFetchConfiguration() - .newFetchState() - : (JDBCFetchState) fetchState; - + JDBCFetchState jfetchState = (JDBCFetchState) fetchState; JDBCFetchConfiguration jfetch = getFetchConfiguration(jfetchState); // get a connection, or reuse current one @@ -492,9 +489,10 @@ public class JDBCStoreManager // now allow the fields to load themselves individually too for (int i = 0, len = fields.length(); i < len; i++) - if (fields.get(i) && !sm.getLoaded().get(i)) - mapping.getFieldMapping(i).load(sm, this, jfetchState); - + if (fields.get(i) && !sm.getLoaded().get(i)) { + FieldMapping fm = mapping.getFieldMapping(i); + fm.load(sm, this, (JDBCFetchState)jfetchState.traverse(fm)); + } mapping.getVersion().afterLoad(sm, this); return true; } catch (ClassNotFoundException cnfe) { @@ -514,8 +512,8 @@ public class JDBCStoreManager } public Collection loadAll(Collection sms, PCState state, int load, - FetchState fetchState, Object context) { - return ImplHelper.loadAll(sms, this, state, load, fetchState, context); + FetchConfiguration fetch, Object context) { + return ImplHelper.loadAll(sms, this, state, load, fetch, context); } public void beforeStateChange(OpenJPAStateManager sm, PCState fromState, @@ -829,23 +827,25 @@ public class JDBCStoreManager for (int i = 0; i < fms.length; i++) { if (fms[i].isPrimaryKey() || sm.getLoaded().get(fms[i].getIndex())) continue; - + // check for eager result, and if not present do standard load eres = res.getEager(fms[i]); res.startDataRequest(fms[i]); try { - if (eres == res) { + if (eres == res) { if (eagerToMany == null && fms[i].isEagerSelectToMany()) eagerToMany = fms[i]; else - fms[i].loadEagerJoin(sm, this, fetchState, res); + fms[i].loadEagerJoin(sm, this, + (JDBCFetchState)fetchState.traverse(fms[i]), res); } else if (eres != null) { - processed = fms[i].loadEagerParallel(sm, this, fetchState, - eres); + processed = fms[i].loadEagerParallel(sm, this, + (JDBCFetchState)fetchState.traverse(fms[i]), eres); if (processed != eres) res.putEager(fms[i], processed); } else - fms[i].load(sm, this, fetchState, res); + fms[i].load(sm, this, + (JDBCFetchState)fetchState.traverse(fms[i]), res); } finally { res.endDataRequest(); } @@ -931,11 +931,11 @@ public class JDBCStoreManager int jtype; int mode; for (int i = 0; i < fms.length; i++) { - if (!requiresSelect(fms[i], sm, fields, fetchState)) - continue; mode = fms[i].getEagerFetchMode(); if (mode == fetch.EAGER_NONE) continue; + if (!requiresSelect(fms[i], sm, fields, fetchState)) + continue; // try to select with join first jtype = (fms[i].getNullValue() == fms[i].NULL_EXCEPTION) ? sel.EAGER_INNER @@ -985,7 +985,7 @@ public class JDBCStoreManager if (sm != null && sm.getPCState() != PCState.TRANSIENT && sm.getLoaded().get(fm.getIndex())) return false; - return fetchState.requiresSelect(fm, true); + return fetchState.requiresFetch(fm); } /** @@ -1059,17 +1059,19 @@ public class JDBCStoreManager esel = sel.getEager(fms[i]); if (esel != null) { if (esel == sel) - fms[i].selectEagerJoin(sel, sm, this, fetchState, eager); + fms[i].selectEagerJoin(sel, sm, this, + (JDBCFetchState)fetchState.traverse(fms[i]), eager); else - fms[i].selectEagerParallel(esel, sm, this, fetchState, - eager); + fms[i].selectEagerParallel(esel, sm, this, + (JDBCFetchState)fetchState.traverse(fms[i]), eager); seld = Math.max(0, seld); } else if (requiresSelect(fms[i], sm, fields, fetchState)) { - fseld = fms[i].select(sel, sm, this, fetchState, eager); + fseld = fms[i].select(sel, sm, this, + (JDBCFetchState)fetchState.traverse(fms[i]), eager); seld = Math.max(fseld, seld); } else if (optSelect(fms[i], sel, sm, fetchState)) { - fseld = fms[i].select(sel, sm, this, fetchState, - fetch.EAGER_NONE); + fseld = fms[i].select(sel, sm, this, + (JDBCFetchState)fetchState.traverse(fms[i]), fetch.EAGER_NONE); // don't upgrade seld to > 0 based on these fields, since // they're not in the calculated field set @@ -1100,7 +1102,7 @@ public class JDBCStoreManager .getLoaded().get(fm.getIndex())) && fm.supportsSelect(sel, sel.TYPE_TWO_PART, sm, this, getFetchConfiguration(fetchState)) > 0 - && fetchState.requiresSelect(fm, true); + && fetchState.requiresFetch(fm); } /** @@ -1141,12 +1143,15 @@ public class JDBCStoreManager fms = subMappings[i].getDefinedFieldMappings(); for (int j = 0; j < fms.length; j++) { // make sure in one of configured fetch groups - if (!fms[j].isInDefaultFetchGroup() - && !fetch.hasFetchGroup(fms[j].getFetchGroups()) - && !fetch.hasField(fms[j].getFullName()) - && (fms[j].isDefaultFetchGroupExplicit() || fms[j] - .supportsSelect(sel, sel.TYPE_TWO_PART, sm, this, fetch) <= 0)) - continue; + if (fetchState.requiresFetch(fms[j]) + || fms[j].supportsSelect(sel, sel.TYPE_TWO_PART, sm, this, fetch) <= 0) + continue; +// if (!fms[j].isInDefaultFetchGroup() +// && !fetch.hasAnyFetchGroup(fms[j].getFetchGroups()) +// && !fetch.hasField(fms[j].getFullName()) +// && (fms[j].isDefaultFetchGroupExplicit() || fms[j] +// .supportsSelect(sel, sel.TYPE_TWO_PART, sm, this, fetch) <= 0)) +// continue; // if we can join to the subclass, do so; much better chance // that the field will be able to select itself without joins @@ -1159,9 +1164,10 @@ public class JDBCStoreManager // if can select with tables already selected, do it if (fms[j].supportsSelect(sel, sel.TYPE_JOINLESS, sm, this, - fetch) > 0) - fms[j] - .select(sel, null, this, fetchState, fetch.EAGER_NONE); + fetch) > 0 && fetchState.requiresFetch(fms[j])) + fms[j].select(sel, null, this, + (JDBCFetchState)fetchState.traverse(fms[j]), + fetch.EAGER_NONE); } } } diff --git a/openjpa-jdbc/src/main/java/org/apache/openjpa/jdbc/kernel/PagingResultObjectProvider.java b/openjpa-jdbc/src/main/java/org/apache/openjpa/jdbc/kernel/PagingResultObjectProvider.java index bf566331d..a63eaee3f 100644 --- a/openjpa-jdbc/src/main/java/org/apache/openjpa/jdbc/kernel/PagingResultObjectProvider.java +++ b/openjpa-jdbc/src/main/java/org/apache/openjpa/jdbc/kernel/PagingResultObjectProvider.java @@ -92,7 +92,7 @@ public class PagingResultObjectProvider BitSet paged = null; for (int i = 0; i < fms.length; i++) { if (fetchState != null - && !fetchState.requiresSelect(fms[i], false)) + && !fetchState.requiresFetch(fms[i])) continue; if (fms[i].supportsSelect(sel, sel.EAGER_PARALLEL, null, store, diff --git a/openjpa-kernel/src/main/java/org/apache/openjpa/abstractstore/AbstractStoreManager.java b/openjpa-kernel/src/main/java/org/apache/openjpa/abstractstore/AbstractStoreManager.java index 17e981aa5..a2a369766 100644 --- a/openjpa-kernel/src/main/java/org/apache/openjpa/abstractstore/AbstractStoreManager.java +++ b/openjpa-kernel/src/main/java/org/apache/openjpa/abstractstore/AbstractStoreManager.java @@ -233,8 +233,8 @@ public abstract class AbstractStoreManager * advantageous. */ public Collection loadAll(Collection sms, PCState state, int load, - FetchState fetchState, Object context) { - return ImplHelper.loadAll(sms, this, state, load, fetchState, context); + FetchConfiguration fetch, Object context) { + return ImplHelper.loadAll(sms, this, state, load, fetch, context); } /** diff --git a/openjpa-kernel/src/main/java/org/apache/openjpa/datacache/DataCacheStoreManager.java b/openjpa-kernel/src/main/java/org/apache/openjpa/datacache/DataCacheStoreManager.java index 9ca86f311..170951fb8 100644 --- a/openjpa-kernel/src/main/java/org/apache/openjpa/datacache/DataCacheStoreManager.java +++ b/openjpa-kernel/src/main/java/org/apache/openjpa/datacache/DataCacheStoreManager.java @@ -408,12 +408,9 @@ public class DataCacheStoreManager } public Collection loadAll(Collection sms, PCState state, int load, - FetchState fetchState, Object edata) { - FetchConfiguration fetch = (fetchState == null) - ? _ctx.getFetchConfiguration() - : fetchState.getFetchConfiguration(); + FetchConfiguration fetch, Object edata) { if (isLocking(fetch)) - return super.loadAll(sms, state, load, fetchState, edata); + return super.loadAll(sms, state, load, fetch, edata); Map unloaded = null; OpenJPAStateManager sm; @@ -435,7 +432,7 @@ public class DataCacheStoreManager //### the 'data.type' access here probably needs //### to be addressed for bug 511 sm.initialize(data.getType(), state); - data.load(sm, fetchState, edata); + data.load(sm, fetch.newFetchState(), edata); } else unloaded = addUnloaded(sm, null, unloaded); } else if (load != FORCE_LOAD_NONE @@ -443,6 +440,7 @@ public class DataCacheStoreManager data = cache.get(sm.getObjectId()); if (data != null) { // load unloaded fields + FetchState fetchState = fetch.newFetchState(); fields = sm.getUnloaded(fetchState); data.load(sm, fields, fetchState, edata); if (fields.length() > 0) @@ -458,7 +456,7 @@ public class DataCacheStoreManager // load with delegate Collection failed = super.loadAll(unloaded.keySet(), state, load, - fetchState, edata); + fetch, edata); if (!_ctx.getPopulateDataCache()) return failed; diff --git a/openjpa-kernel/src/main/java/org/apache/openjpa/enhance/PCDataGenerator.java b/openjpa-kernel/src/main/java/org/apache/openjpa/enhance/PCDataGenerator.java index 8321bab8e..ed3d93e7c 100644 --- a/openjpa-kernel/src/main/java/org/apache/openjpa/enhance/PCDataGenerator.java +++ b/openjpa-kernel/src/main/java/org/apache/openjpa/enhance/PCDataGenerator.java @@ -575,7 +575,7 @@ public class PCDataGenerator code.invokevirtual().setMethod(FieldMetaData.class, "getFetchGroups", Set.class, null); code.invokeinterface().setMethod - (FetchConfiguration.class, "hasFetchGroup", + (FetchConfiguration.class, "hasAnyFetchGroup", boolean.class, new Class[]{ Set.class }); JumpInstruction ifins = code.ifne(); code.aload().setLocal(fetch); diff --git a/openjpa-kernel/src/main/java/org/apache/openjpa/kernel/BrokerImpl.java b/openjpa-kernel/src/main/java/org/apache/openjpa/kernel/BrokerImpl.java index 4b589a56e..f6ff06547 100644 --- a/openjpa-kernel/src/main/java/org/apache/openjpa/kernel/BrokerImpl.java +++ b/openjpa-kernel/src/main/java/org/apache/openjpa/kernel/BrokerImpl.java @@ -694,11 +694,13 @@ public class BrokerImpl int flags = OID_COPY | OID_ALLOW_NEW | OID_NODELETED; if (!validate) flags |= OID_NOVALIDATE; - return find(oid, null, null, null, flags, call); + return find(oid, _fc.newFetchState (), null, null, flags, call); } public Object find(Object oid, FetchState fetchState, BitSet exclude, Object edata, int flags) { + if (fetchState == null) + fetchState = _fc.newFetchState (); return find(oid, fetchState, exclude, edata, flags, null); } @@ -717,8 +719,6 @@ public class BrokerImpl } beginOperation(true); - if (fetchState == null) - fetchState = _fc.newFetchState(); try { assertNontransactionalRead(); @@ -842,18 +842,18 @@ public class BrokerImpl int flags = OID_COPY | OID_ALLOW_NEW | OID_NODELETED; if (!validate) flags |= OID_NOVALIDATE; - return findAll(oids, null, null, null, flags, call); + return findAll(oids, _fc, null, null, flags, call); } - public Object[] findAll(Collection oids, FetchState fetchState, + public Object[] findAll(Collection oids, FetchConfiguration fetch, BitSet exclude, Object edata, int flags) { - return findAll(oids, fetchState, exclude, edata, flags, null); + return findAll(oids, fetch, exclude, edata, flags, null); } /** * Internal finder. */ - protected Object[] findAll(Collection oids, FetchState fetchState, + protected Object[] findAll(Collection oids, FetchConfiguration fetch, BitSet exclude, Object edata, int flags, FindCallbacks call) { // throw any exceptions for null oids up immediately if (oids == null) @@ -867,9 +867,6 @@ public class BrokerImpl _loading = new HashMap((int) (oids.size() * 1.33 + 1)); if (call == null) call = this; - if (fetchState == null) - fetchState = _fc.newFetchState(); - FetchConfiguration fetch = fetchState.getFetchConfiguration(); beginOperation(true); try { assertNontransactionalRead(); @@ -915,7 +912,7 @@ public class BrokerImpl PCState state = (transState) ? PCState.PCLEAN : PCState.PNONTRANS; Collection failed = _store.loadAll(load, state, - StoreManager.FORCE_LOAD_NONE, fetchState, edata); + StoreManager.FORCE_LOAD_NONE, _fc, edata); // set failed instances to null if (failed != null && !failed.isEmpty()) { @@ -937,8 +934,8 @@ public class BrokerImpl sm = (StateManagerImpl) _loading.get(oid); if (sm != null && requiresLoad(sm, true, edata, flags)) { try { - sm.load(fetchState, StateManagerImpl.LOAD_FGS, exclude, - edata, false); + sm.load(fetch.newFetchState(), StateManagerImpl.LOAD_FGS, + exclude, edata, false); if (active) { _lm.lock(sm, level, fetch.getLockTimeout(), edata); sm.readLocked(level, fetch.getWriteLockLevel()); @@ -2687,7 +2684,7 @@ public class BrokerImpl // refresh all if (load != null) { Collection failed = _store.loadAll(load, null, - _store.FORCE_LOAD_REFRESH, _fc.newFetchState(), null); + _store.FORCE_LOAD_REFRESH, _fc, null); if (failed != null && !failed.isEmpty()) exceps = add(exceps, newObjectNotFoundException(failed)); @@ -2812,8 +2809,7 @@ public class BrokerImpl if (load != null) { int mode = (dfgOnly) ? _store.FORCE_LOAD_DFG : _store.FORCE_LOAD_ALL; - failed = _store.loadAll(load, null, mode, _fc.newFetchState(), - null); + failed = _store.loadAll(load, null, mode, _fc, null); if (failed != null && !failed.isEmpty()) exceps = add(exceps, newObjectNotFoundException(failed)); } @@ -3196,7 +3192,7 @@ public class BrokerImpl Collection failed = null; if (load != null) { failed = _store.loadAll(load, null, _store.FORCE_LOAD_NONE, - _fc.newFetchState(), null); + _fc, null); if (failed != null && !failed.isEmpty()) exceps = add(exceps, newObjectNotFoundException(failed)); @@ -4087,7 +4083,7 @@ public class BrokerImpl Object oid = ApplicationIds.create(pc, meta); if (oid == null) return false; - return find(oid, _fc.newFetchState(), EXCLUDE_ALL, null, 0) != null; + return find(oid, null, EXCLUDE_ALL, null, 0) != null; } public OpenJPAStateManager getStateManager(Object obj) { diff --git a/openjpa-kernel/src/main/java/org/apache/openjpa/kernel/DelegatingBroker.java b/openjpa-kernel/src/main/java/org/apache/openjpa/kernel/DelegatingBroker.java index 741d187d3..7e04d5d58 100644 --- a/openjpa-kernel/src/main/java/org/apache/openjpa/kernel/DelegatingBroker.java +++ b/openjpa-kernel/src/main/java/org/apache/openjpa/kernel/DelegatingBroker.java @@ -198,10 +198,10 @@ public class DelegatingBroker } } - public Object[] findAll(Collection oids, FetchState fetchState, + public Object[] findAll(Collection oids, FetchConfiguration fetch, BitSet exclude, Object edata, int flags) { try { - return _broker.findAll(oids, fetchState, exclude, edata, flags); + return _broker.findAll(oids, fetch, exclude, edata, flags); } catch (RuntimeException re) { throw translate(re); } diff --git a/openjpa-kernel/src/main/java/org/apache/openjpa/kernel/DelegatingFetchConfiguration.java b/openjpa-kernel/src/main/java/org/apache/openjpa/kernel/DelegatingFetchConfiguration.java index 392d9fa3f..b9c6ad7a6 100644 --- a/openjpa-kernel/src/main/java/org/apache/openjpa/kernel/DelegatingFetchConfiguration.java +++ b/openjpa-kernel/src/main/java/org/apache/openjpa/kernel/DelegatingFetchConfiguration.java @@ -229,9 +229,9 @@ public class DelegatingFetchConfiguration } } - public boolean hasFetchGroup(Set groups) { + public boolean hasAnyFetchGroup(Set groups) { try { - return _fetch.hasFetchGroup(groups); + return _fetch.hasAnyFetchGroup(groups); } catch (RuntimeException re) { throw translate(re); } diff --git a/openjpa-kernel/src/main/java/org/apache/openjpa/kernel/DelegatingStoreManager.java b/openjpa-kernel/src/main/java/org/apache/openjpa/kernel/DelegatingStoreManager.java index 41e37ec39..43a672f26 100644 --- a/openjpa-kernel/src/main/java/org/apache/openjpa/kernel/DelegatingStoreManager.java +++ b/openjpa-kernel/src/main/java/org/apache/openjpa/kernel/DelegatingStoreManager.java @@ -114,8 +114,8 @@ public abstract class DelegatingStoreManager } public Collection loadAll(Collection sms, PCState state, int load, - FetchState fetchState, Object context) { - return _store.loadAll(sms, state, load, fetchState, context); + FetchConfiguration fetch, Object context) { + return _store.loadAll(sms, state, load, fetch, context); } public void beforeStateChange(OpenJPAStateManager sm, PCState fromState, diff --git a/openjpa-kernel/src/main/java/org/apache/openjpa/kernel/DetachManager.java b/openjpa-kernel/src/main/java/org/apache/openjpa/kernel/DetachManager.java index b6a35b921..0e71c66e4 100644 --- a/openjpa-kernel/src/main/java/org/apache/openjpa/kernel/DetachManager.java +++ b/openjpa-kernel/src/main/java/org/apache/openjpa/kernel/DetachManager.java @@ -223,7 +223,7 @@ public class DetachManager FieldMetaData[] fmds = sm.getMetaData().getFields(); for (int i = 0; i < fmds.length; i++) { if (fmds[i].isPrimaryKey() || fmds[i].isInDefaultFetchGroup() - || fetch.hasFetchGroup(fmds[i].getFetchGroups()) + || fetch.hasAnyFetchGroup(fmds[i].getFetchGroups()) || fetch.hasField(fmds[i].getFullName())) idxs.set(i); } diff --git a/openjpa-kernel/src/main/java/org/apache/openjpa/kernel/DetachedStateManager.java b/openjpa-kernel/src/main/java/org/apache/openjpa/kernel/DetachedStateManager.java index fe62450c9..3a73d1e22 100644 --- a/openjpa-kernel/src/main/java/org/apache/openjpa/kernel/DetachedStateManager.java +++ b/openjpa-kernel/src/main/java/org/apache/openjpa/kernel/DetachedStateManager.java @@ -136,9 +136,10 @@ public class DetachedStateManager load.set(i); } } - - sm.loadFields(load, null, broker.getFetchConfiguration(). - getWriteLockLevel(), null, true); + FetchConfiguration fc = broker.getFetchConfiguration(); + FetchState fetchState = fc.newFetchState(); + sm.loadFields(load, fetchState, fc.getWriteLockLevel(), null, true); + } sm.setVersion(_version); diff --git a/openjpa-kernel/src/main/java/org/apache/openjpa/kernel/FetchConfiguration.java b/openjpa-kernel/src/main/java/org/apache/openjpa/kernel/FetchConfiguration.java index 11a189089..e925ae316 100644 --- a/openjpa-kernel/src/main/java/org/apache/openjpa/kernel/FetchConfiguration.java +++ b/openjpa-kernel/src/main/java/org/apache/openjpa/kernel/FetchConfiguration.java @@ -45,6 +45,7 @@ public interface FetchConfiguration public static final String FETCH_GROUP_ALL = "org.apache.openjpa.kernel.FetchConfiguration.FETCH_GROUP_ALL"; + public static final String FETCH_GROUP_DEFAULT = "default"; /** * Return the context assiciated with this configuration; * may be null if it has not been set or this object has been serialized. @@ -144,7 +145,7 @@ public interface FetchConfiguration * * @since 4.1 */ - public boolean hasFetchGroup(Set groups); + public boolean hasAnyFetchGroup(Set groups); /** * Adds group to the set of fetch group names to diff --git a/openjpa-kernel/src/main/java/org/apache/openjpa/kernel/FetchConfigurationImpl.java b/openjpa-kernel/src/main/java/org/apache/openjpa/kernel/FetchConfigurationImpl.java index cf5ca3e69..03f4c1909 100644 --- a/openjpa-kernel/src/main/java/org/apache/openjpa/kernel/FetchConfigurationImpl.java +++ b/openjpa-kernel/src/main/java/org/apache/openjpa/kernel/FetchConfigurationImpl.java @@ -108,6 +108,7 @@ public class FetchConfigurationImpl public void copy(FetchConfiguration fetch) { setFetchBatchSize(fetch.getFetchBatchSize()); + setMaxFetchDepth(fetch.getMaxFetchDepth()); setQueryCache(fetch.getQueryCache()); setFlushBeforeQueries(fetch.getFlushBeforeQueries()); setLockTimeout(fetch.getLockTimeout()); @@ -172,11 +173,11 @@ public class FetchConfigurationImpl public synchronized boolean hasFetchGroup(String group) { return _fetchGroups != null - && ((group != null && _fetchGroups.contains(group)) + && (_fetchGroups.contains(group) || _fetchGroups.contains(FETCH_GROUP_ALL)); } - public synchronized boolean hasFetchGroup(Set groups) { + public synchronized boolean hasAnyFetchGroup(Set groups) { if (_fetchGroups != null && groups != null) { Iterator iter = groups.iterator(); while (iter.hasNext()) { diff --git a/openjpa-kernel/src/main/java/org/apache/openjpa/kernel/FetchState.java b/openjpa-kernel/src/main/java/org/apache/openjpa/kernel/FetchState.java index 62e7c805e..57a1c3c93 100644 --- a/openjpa-kernel/src/main/java/org/apache/openjpa/kernel/FetchState.java +++ b/openjpa-kernel/src/main/java/org/apache/openjpa/kernel/FetchState.java @@ -1,68 +1,135 @@ -/* - * Copyright 2006 The Apache Software Foundation. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ -package org.apache.openjpa.kernel; - -import org.apache.openjpa.meta.FieldMetaData; - -/** - * Defines the decision to include fields for selection or loading during - * a fetch operation. - * - * @author root + * state. + * + * @author 0) context.saveFields(true); context.clearFields(); - context.load(context.getBroker().getFetchConfiguration(). - newFetchState(), context.LOAD_FGS, null, null, true); + context.load(null, context.LOAD_FGS, null, null, true); } return PDIRTY; } diff --git a/openjpa-kernel/src/main/java/org/apache/openjpa/kernel/StateManagerImpl.java b/openjpa-kernel/src/main/java/org/apache/openjpa/kernel/StateManagerImpl.java index f2dab9791..c15023eb8 100644 --- a/openjpa-kernel/src/main/java/org/apache/openjpa/kernel/StateManagerImpl.java +++ b/openjpa-kernel/src/main/java/org/apache/openjpa/kernel/StateManagerImpl.java @@ -18,14 +18,7 @@ package org.apache.openjpa.kernel; import java.io.IOException; import java.io.ObjectOutput; import java.lang.reflect.Modifier; -import java.util.ArrayList; -import java.util.Arrays; -import java.util.BitSet; -import java.util.Calendar; -import java.util.Comparator; -import java.util.Date; -import java.util.HashMap; -import java.util.TimeZone; +import java.util.*; import org.apache.commons.lang.StringUtils; import org.apache.openjpa.conf.OpenJPAConfiguration; @@ -325,6 +318,8 @@ public class StateManagerImpl if (!forWrite && (!isPersistent() || isNew() || isDeleted())) return false; + if (fetchState==null) + fetchState = _broker.getFetchConfiguration().newFetchState(); // if any fields being loaded, do state transitions for read BitSet fields = getUnloadedInternal(fetchState, loadMode, exclude); boolean active = _broker.isActive(); @@ -2760,9 +2755,9 @@ public class StateManagerImpl protected void loadField(int field, int lockLevel, boolean forWrite, boolean fgs) { - loadField(field, _broker.getFetchConfiguration().newFetchState(), - lockLevel, forWrite, fgs); - } + FetchConfiguration fc = _broker.getFetchConfiguration(); + loadField(field, fc.newFetchState(),lockLevel, forWrite, fgs); + } /** * Load the given field's fetch group; the field itself may already be @@ -2799,7 +2794,7 @@ public class StateManagerImpl // call this method even if there are no unloaded fields; loadFields // takes care of things like loading version info and setting PC // flags - loadFields(fields, null, lockLevel, null, forWrite); + loadFields(fields, fetchState, lockLevel, null, forWrite); } /** @@ -2869,15 +2864,12 @@ public class StateManagerImpl // is this field in the dfg? FieldMetaData[] fmds = _meta.getDefaultFetchGroupFields(); - if (fmds.length > 0 && field != -1 - && !requiredByDefault(_meta.getField(field), fetchState)) - return; - // see if the dfg is fully loaded + // see if any fetch group with postLoad=true is fully loaded boolean isLoaded = true; for (int i = 0; isLoaded && i < fmds.length; i++) if (!_loaded.get(fmds[i].getIndex()) - && requiredByDefault(fmds[i], fetchState)) + && requiresPostLoadCallabck(fmds[i], fetchState)) isLoaded = false; if (isLoaded) { _flags |= FLAG_DFG; @@ -2885,15 +2877,18 @@ public class StateManagerImpl } } - private boolean requiredByDefault(FieldMetaData fm, FetchState fetchState) { + private boolean requiresPostLoadCallabck(FieldMetaData fm, FetchState fetchState) { if (fm == null) return false; - if (fetchState == null) - return fm.isInDefaultFetchGroup() - && _broker.getFetchConfiguration().hasFetchGroup - (FetchGroup.getDefaultGroupName()); - else - return fetchState.isDefault(fm); + Set fetchGroups = fm.getFetchGroups(); + for (Iterator i = fetchGroups.iterator(); i.hasNext();) + { + String fg = i.next().toString(); + if (_broker.getFetchConfiguration().hasFetchGroup(fg) + && fm.getDeclaringMetaData().getFetchGroup(fg).isPostLoad()) + return true; + } + return false; } /** diff --git a/openjpa-kernel/src/main/java/org/apache/openjpa/kernel/StoreContext.java b/openjpa-kernel/src/main/java/org/apache/openjpa/kernel/StoreContext.java index 1f56d3e5f..86772af7f 100644 --- a/openjpa-kernel/src/main/java/org/apache/openjpa/kernel/StoreContext.java +++ b/openjpa-kernel/src/main/java/org/apache/openjpa/kernel/StoreContext.java @@ -143,7 +143,7 @@ public interface StoreContext { * * @see #find(Object,FetchState,BitSet,Object,int) */ - public Object[] findAll(Collection oids, FetchState fetchState, + public Object[] findAll(Collection oids, FetchConfiguration fetch, BitSet exclude, Object edata, int flags); /** diff --git a/openjpa-kernel/src/main/java/org/apache/openjpa/kernel/StoreManager.java b/openjpa-kernel/src/main/java/org/apache/openjpa/kernel/StoreManager.java index f701d6b0e..c1e9f9609 100644 --- a/openjpa-kernel/src/main/java/org/apache/openjpa/kernel/StoreManager.java +++ b/openjpa-kernel/src/main/java/org/apache/openjpa/kernel/StoreManager.java @@ -210,7 +210,7 @@ public interface StoreManager * @see org.apache.openjpa.util.ImplHelper#loadAll */ public Collection loadAll(Collection sms, PCState state, int load, - FetchState fetchState, Object edata); + FetchConfiguration fetch, Object edata); /** * Notification that the given state manager is about to change its diff --git a/openjpa-kernel/src/main/java/org/apache/openjpa/kernel/VersionAttachStrategy.java b/openjpa-kernel/src/main/java/org/apache/openjpa/kernel/VersionAttachStrategy.java index 7320eccd3..fbbcd41ab 100644 --- a/openjpa-kernel/src/main/java/org/apache/openjpa/kernel/VersionAttachStrategy.java +++ b/openjpa-kernel/src/main/java/org/apache/openjpa/kernel/VersionAttachStrategy.java @@ -130,7 +130,7 @@ class VersionAttachStrategy break; case DETACH_FGS: if (fmds[i].isInDefaultFetchGroup() - || fetch.hasFetchGroup(fmds[i].getFetchGroups()) + || fetch.hasAnyFetchGroup(fmds[i].getFetchGroups()) || fetch.hasField(fmds[i].getFullName())) attachField(manager, toAttach, sm, fmds[i], true); break; diff --git a/openjpa-kernel/src/main/java/org/apache/openjpa/meta/ClassMetaData.java b/openjpa-kernel/src/main/java/org/apache/openjpa/meta/ClassMetaData.java index 8108c8778..35b09199a 100644 --- a/openjpa-kernel/src/main/java/org/apache/openjpa/meta/ClassMetaData.java +++ b/openjpa-kernel/src/main/java/org/apache/openjpa/meta/ClassMetaData.java @@ -1922,10 +1922,12 @@ public class ClassMetaData * the same name. */ public synchronized FetchGroup addFetchGroup(String name) { + if (name == null || name.trim().length()==0) + throw new MetaDataException(_loc.get("empty-fg-name", this)); FetchGroup fg = (FetchGroup) _fgs.get(name); if (fg == null) { - fg = newFetchGroup(name); - _fgs.put(name, fg); + fg = new FetchGroup(this, name); + _fgs.put(name, fg); } return fg; @@ -1933,33 +1935,19 @@ public class ClassMetaData /** * Gets a named fecth group. If not available in this receiver then looks - * up the inheritence hierarchy. Creates if it does not exist and - * mustBe is false. + * up the inheritence hierarchy. * * @param name name of a fetch group. - * @param mustBe if true then the named group must exist in this receiver - * or any of its persistent super classes. - * @return an existing or newly created fecth group of the given name. + * @return an existing fecth group of the given name if known to this + * receiver or any of its superclasses. Otherwise null. */ - public synchronized FetchGroup getFetchGroup(String name, boolean mustBe) { + public synchronized FetchGroup getFetchGroup(String name) { FetchGroup fg = (FetchGroup) _fgs.get(name); if (fg == null) { ClassMetaData scm = getPCSuperclassMetaData(); if (scm != null) - fg = scm.getFetchGroup(name, false); + fg = scm.getFetchGroup(name); } - - if (fg == null) - if (mustBe) - return null; - else - fg = addFetchGroup(name); - - return fg; - } - - protected FetchGroup newFetchGroup(String name) { - FetchGroup fg = new FetchGroup(this, name); return fg; } diff --git a/openjpa-kernel/src/main/java/org/apache/openjpa/meta/FetchGroup.java b/openjpa-kernel/src/main/java/org/apache/openjpa/meta/FetchGroup.java index ca0ddb91b..c0a4fb31d 100644 --- a/openjpa-kernel/src/main/java/org/apache/openjpa/meta/FetchGroup.java +++ b/openjpa-kernel/src/main/java/org/apache/openjpa/meta/FetchGroup.java @@ -1,205 +1,173 @@ -/* - * Copyright 2006 The Apache Software Foundation. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ -/** - * - */ -package org.apache.openjpa.meta; - -import java.io.File; -import java.util.ArrayList; -import java.util.HashMap; -import java.util.Iterator; -import java.util.List; -import java.util.Map; - -import org.apache.commons.lang.StringUtils; -import org.apache.openjpa.lib.meta.SourceTracker; -import org.apache.openjpa.lib.util.Localizer; -import org.apache.openjpa.util.MetaDataException; - -/** - * Captures fetch group metadata. - */ -public class FetchGroup - implements SourceTracker { - - private final String _name; - private final ClassMetaData _declaringClass; - private List _includes; - private Map _depths; - - public static final int DEFAULT_RECURSION_DEPTH = 1; - private static String DEFAULT_GROUP_NAME = "default"; - - private static final Localizer _loc = Localizer.forPackage - (FetchGroup.class); - - /** - * Supply immutable name. - * - * @param name must not by null or empty. - */ - FetchGroup(ClassMetaData cm, String name) { - super(); - - if (cm == null) - throw new MetaDataException(_loc.get("null-class-fg", name)); - if (StringUtils.isEmpty(name)) - throw new MetaDataException(_loc.get("invalid-fg-name", cm, - name)); - - _name = name; - _declaringClass = cm; - } - - public String getName() { - return _name; - } - - /** - * Includes given fetch group within this receiver. - * - * @param fg must not be null or this receiver itself or must not include - * this receiver. - */ - public void addInclude(FetchGroup fg) { - if (fg == this) - throw new MetaDataException(_loc.get("self-include-fg", this)); - if (fg == null) - throw new MetaDataException(_loc.get("null-include-fg", this)); - if (fg.includes(this, true)) - throw new MetaDataException(_loc.get("cyclic-fg", this, fg)); - - if (_includes == null) - _includes = new ArrayList(); - _includes.add(fg); - } - - /** - * Affirms if given fetch group is included by this receiver. - * - * @param fg - * @param recurse if true then recursively checks within the included - * fecth groups. Otherwise just checks within direct includes. - */ - public boolean includes(FetchGroup fg, boolean recurse) { - if (_includes == null) - return false; - if (_includes.contains(fg)) - return true; - - if (recurse) - for (Iterator i = _includes.iterator(); i.hasNext();) - if (((FetchGroup) i.next()).includes(fg, true)) - return true; - - return false; - } - - /** - * Sets recursion depth for a field. - * - * @param fm - * @param depth - */ - public void setDepthFor(FieldMetaData fm, int depth) { - if (depth < -1) - throw new MetaDataException(_loc.get("invalid-fetch-depth", - _name, fm, new Integer(depth))); - - if (_depths == null) - _depths = new HashMap(); - - _depths.put(fm, new Integer(depth)); - } - - /** - * Gets recusrion depth for the given field. - * - * @param fm - * @return defaults to 1. - */ - public int getDepthFor(FieldMetaData fm) { - if (_depths == null || !_depths.containsKey(fm)) - return DEFAULT_RECURSION_DEPTH; - - return ((Integer) _depths.get(fm)).intValue(); - } - - /** - * Set the name for default group. - * It is expected to be set only once by a compliant implementation. - * If multiple attempts are made to set the default group name, - * then an attempt will succeed only for the first time or if the given - * name matches with the current name. - * - * @param name of the default fetch group - */ - public static void setDefaultGroupName(String name) { - //###JDO2 -- better mechanics required to set default group name - DEFAULT_GROUP_NAME = name; - } - - /** - * Get the name in which default fetch group is known. - * - * @return name of the default group. Can be null, if not set. - */ - public static final String getDefaultGroupName() { - return DEFAULT_GROUP_NAME; - } - - /** - * Affirms equality if the other has the same name. - */ - public boolean equals(Object other) { - if (other instanceof FetchGroup) { - FetchGroup that = (FetchGroup) other; - return _name.equals(that._name) - && _declaringClass.equals(that._declaringClass); - } - - return false; - } - - public int hashCode() { - return _name.hashCode() + _declaringClass.hashCode(); - } - - public String toString() { - return _name; - } - - ///////////////// - // SourceTracker - ///////////////// - - public File getSourceFile() { - return _declaringClass.getSourceFile(); - } - - public Object getSourceScope() { - return _declaringClass; - } - - public int getSourceType() { - return _declaringClass.getSourceType(); - } - - public String getResourceName() { - return _declaringClass.getResourceName (); - } -} +/* + * Copyright 2006 The Apache Software Foundation. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * http://www.apache.org/licenses/LICENSE-2.0 + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +/** + * + */ +package org.apache.openjpa.meta; + +import java.io.File; +import java.util.ArrayList; +import java.util.HashMap; +import java.util.Iterator; +import java.util.List; +import java.util.Map; + +import org.apache.commons.lang.StringUtils; +import org.apache.openjpa.lib.meta.SourceTracker; +import org.apache.openjpa.lib.util.Localizer; +import org.apache.openjpa.util.UserException; + +/** + * Captures fetch group metadata. + */ +public class FetchGroup implements SourceTracker { + + private final String _name; + private final ClassMetaData _declaringClass; + private List _includes; + private Map _depths; + private boolean _postLoad; + public static final int DEFAULT_RECURSION_DEPTH = 1; + private static final Localizer _loc = + Localizer.forPackage(FetchGroup.class); + + /** + * Supply immutable name. + * + * @param must not by null or empty. + */ + FetchGroup(ClassMetaData cm, String name) { + super(); + if (StringUtils.isEmpty(name)) + throw new UserException(_loc.get("invalid-fg-name", cm, name)); + _name = name; + _declaringClass = cm; + } + + public String getName() { + return _name; + } + + /** + * Includes given fetch group within this receiver. + * + * @param fg must not be null or this receiver itself or must not include + * this receiver. + */ + public void addInclude(FetchGroup fg) { + if (fg == this) + throw new UserException(_loc.get("self-include-fg", this)); + if (fg == null) + throw new UserException(_loc.get("null-include-fg", this)); + if (fg.includes(this, true)) + throw new UserException(_loc.get("cyclic-fg", this, fg)); + if (_includes == null) + _includes = new ArrayList(); + _includes.add(fg); + } + + /** + * Affirms if given fetch group is included by this receiver. + * + * @param fg + * @param recurse if true then recursively checks within the included + * fecth groups. Otherwise just checks within direct includes. + * @return + */ + public boolean includes(FetchGroup fg, boolean recurse) { + if (_includes == null) + return false; + if (_includes.contains(fg)) + return true; + if (recurse) + for (Iterator i = _includes.iterator(); i.hasNext();) + if (((FetchGroup) i.next()).includes(fg, true)) + return true; + return false; + } + + /** + * Sets recursion depth for a field. + * + * @param fm + * @param depth + */ + public void setDepthFor(FieldMetaData fm, int depth) { + if (depth < -1) + throw new UserException(_loc.get("invalid-fetch-depth", + _name, fm, new Integer(depth))); + if (_depths == null) + _depths = new HashMap(); + _depths.put(fm, new Integer(depth)); + } + + /** + * Gets recusrion depth for the given field. + * + * @param fm + * @return defaults to 1. + */ + public int getDepthFor(FieldMetaData fm) { + if (_depths == null || !_depths.containsKey(fm)) + return DEFAULT_RECURSION_DEPTH; + return ((Integer) _depths.get(fm)).intValue(); + } + + + public boolean isPostLoad () { + return _postLoad; + } + + public void setPostLoad (boolean flag) { + _postLoad = flag; + } + + /** + * Affirms equality if the other has the same name. + */ + public boolean equals(Object other) { + if (other instanceof FetchGroup) { + FetchGroup that = (FetchGroup) other; + return _name.equals(that._name) + && _declaringClass.equals(that._declaringClass); + } + return false; + } + + public int hashCode() { + return _name.hashCode() + _declaringClass.hashCode(); + } + + public String toString() { + return _name; + } + + ///////////////// + // SourceTracker + ///////////////// + public File getSourceFile() { + return _declaringClass.getSourceFile(); + } + + public Object getSourceScope() { + return _declaringClass; + } + + public int getSourceType() { + return _declaringClass.getSourceType(); + } + + public String getResourceName() { + return _declaringClass.getResourceName(); + } +} diff --git a/openjpa-kernel/src/main/java/org/apache/openjpa/meta/FieldMetaData.java b/openjpa-kernel/src/main/java/org/apache/openjpa/meta/FieldMetaData.java index fb2c680bf..f3e58e962 100644 --- a/openjpa-kernel/src/main/java/org/apache/openjpa/meta/FieldMetaData.java +++ b/openjpa-kernel/src/main/java/org/apache/openjpa/meta/FieldMetaData.java @@ -39,6 +39,7 @@ import org.apache.commons.collections.comparators.ComparatorChain; import org.apache.commons.lang.StringUtils; import org.apache.openjpa.conf.OpenJPAConfiguration; import org.apache.openjpa.enhance.PersistenceCapable; +import org.apache.openjpa.kernel.FetchConfiguration; import org.apache.openjpa.kernel.OpenJPAStateManager; import org.apache.openjpa.kernel.StoreContext; import org.apache.openjpa.lib.conf.Configurations; @@ -849,13 +850,13 @@ public class FieldMetaData */ public void addFetchGroup(String fg) { if (StringUtils.isEmpty(fg)) - return; - if (getDeclaringMetaData().getFetchGroup(fg, false) == null) + throw new MetaDataException(_loc.get("bad-fg", fg)); + if (getDeclaringMetaData().getFetchGroup(fg) == null) throw new MetaDataException(_loc.get("unknown-fg", fg)); if (_fgs == null) _fgs = new HashSet(); _fgs.add(fg); - if (fg.equals(FetchGroup.getDefaultGroupName())) + if (fg.equals(FetchConfiguration.FETCH_GROUP_DEFAULT)) setInDefaultFetchGroup(true); } @@ -863,7 +864,7 @@ public class FieldMetaData if (_fgs == null) return; _fgs.remove(fg); - if (fg != null && fg.equals(FetchGroup.getDefaultGroupName())) + if (FetchConfiguration.FETCH_GROUP_DEFAULT.equals(fg)) setInDefaultFetchGroup(false); } diff --git a/openjpa-kernel/src/main/java/org/apache/openjpa/util/ImplHelper.java b/openjpa-kernel/src/main/java/org/apache/openjpa/util/ImplHelper.java index a647c2ff5..e9e46162c 100644 --- a/openjpa-kernel/src/main/java/org/apache/openjpa/util/ImplHelper.java +++ b/openjpa-kernel/src/main/java/org/apache/openjpa/util/ImplHelper.java @@ -23,6 +23,7 @@ import java.util.Iterator; import org.apache.commons.lang.StringUtils; import org.apache.openjpa.enhance.PersistenceCapable; +import org.apache.openjpa.kernel.FetchConfiguration; import org.apache.openjpa.kernel.FetchState; import org.apache.openjpa.kernel.LockManager; import org.apache.openjpa.kernel.OpenJPAStateManager; @@ -90,18 +91,18 @@ public class ImplHelper { * @since 4.0 */ public static Collection loadAll(Collection sms, StoreManager store, - PCState state, int load, FetchState fetchState, Object context) { + PCState state, int load, FetchConfiguration fetch, Object context) { Collection failed = null; OpenJPAStateManager sm; LockManager lm; for (Iterator itr = sms.iterator(); itr.hasNext();) { sm = (OpenJPAStateManager) itr.next(); + FetchState fetchState = fetch.newFetchState(); if (sm.getManagedInstance() == null) { if (!store.initialize(sm, state, fetchState, context)) failed = addFailedId(sm, failed); } else if (load != StoreManager.FORCE_LOAD_NONE || sm.getPCState() == PCState.HOLLOW) { - lm = sm.getContext().getLockManager(); if (!store.load(sm, sm.getUnloaded(fetchState), fetchState, lm.getLockLevel(sm), context))