You are viewing a plain text version of this content. The canonical link for it is here.
Posted to dev@openjpa.apache.org by Michael Dick <mi...@gmail.com> on 2008/05/05 17:32:07 UTC

Re: svn commit: r652913 - in /openjpa/trunk: openjpa-jdbc/src/main/java/org/apache/openjpa/jdbc/conf/ openjpa-jdbc/src/main/java/org/apache/openjpa/jdbc/kernel/ openjpa-jdbc/src/main/java/org/apache/openjpa/jdbc/meta/strats/ openjpa-jdbc/src/main/jav

I think it was the WebSphere UOW code I committed earlier that caused the
problem. Anyway it should be fixed with rev 653499. I had to exclude the
internal repository directory from the rat scan.

Note that the excludes won't work if you run :
   $ mvn rat:check

but will work if you run :
   $ mvn -Plicense-verify-profile rat:check

-mike

On Fri, May 2, 2008 at 10:16 PM, Patrick Linskey <pl...@gmail.com> wrote:

> Hi,
>
> This is failing the license header check test in the snapshot build.
>
> -Patrick
>
>
> On May 2, 2008, at 2:09 PM, mikedd@apache.org wrote:
>
>  Author: mikedd
> > Date: Fri May  2 14:09:14 2008
> > New Revision: 652913
> >
> > URL: http://svn.apache.org/viewvc?rev=652913&view=rev
> > Log:
> > OPENJPA-407 committing patch provided by Fay Wang and Jeremy Bauer
> >
> > Added:
> >
> > openjpa/trunk/openjpa-jdbc/src/main/java/org/apache/openjpa/jdbc/conf/QuerySQLCacheValue.java
> >   (with props)
> >
> > openjpa/trunk/openjpa-persistence-jdbc/src/test/java/org/apache/openjpa/kernel/TestQuerySQLCache.java
> >   (with props)
> > Modified:
> >
> > openjpa/trunk/openjpa-jdbc/src/main/java/org/apache/openjpa/jdbc/conf/JDBCConfiguration.java
> >
> > openjpa/trunk/openjpa-jdbc/src/main/java/org/apache/openjpa/jdbc/conf/JDBCConfigurationImpl.java
> >
> > openjpa/trunk/openjpa-jdbc/src/main/java/org/apache/openjpa/jdbc/kernel/JDBCStoreManager.java
> >
> > openjpa/trunk/openjpa-jdbc/src/main/java/org/apache/openjpa/jdbc/meta/strats/RelationFieldStrategy.java
> >
> > openjpa/trunk/openjpa-jdbc/src/main/java/org/apache/openjpa/jdbc/meta/strats/StoreCollectionFieldStrategy.java
> >
> > openjpa/trunk/openjpa-jdbc/src/main/java/org/apache/openjpa/jdbc/sql/LogicalUnion.java
> >
> > openjpa/trunk/openjpa-jdbc/src/main/java/org/apache/openjpa/jdbc/sql/SQLBuffer.java
> >
> > openjpa/trunk/openjpa-jdbc/src/main/java/org/apache/openjpa/jdbc/sql/Select.java
> >
> > openjpa/trunk/openjpa-jdbc/src/main/java/org/apache/openjpa/jdbc/sql/SelectExecutor.java
> >
> > openjpa/trunk/openjpa-jdbc/src/main/java/org/apache/openjpa/jdbc/sql/SelectImpl.java
> >
> > openjpa/trunk/openjpa-jdbc/src/main/resources/org/apache/openjpa/jdbc/kernel/localizer.properties
> >
> > openjpa/trunk/openjpa-jdbc/src/main/resources/org/apache/openjpa/jdbc/meta/strats/localizer.properties
> >
> > openjpa/trunk/openjpa-kernel/src/main/java/org/apache/openjpa/kernel/FetchConfigurationImpl.java
> >   openjpa/trunk/openjpa-project/src/doc/manual/ref_guide_caching.xml
> >   openjpa/trunk/openjpa-project/src/doc/manual/ref_guide_conf.xml
> >
> > Modified:
> > openjpa/trunk/openjpa-jdbc/src/main/java/org/apache/openjpa/jdbc/conf/JDBCConfiguration.java
> > URL:
> > http://svn.apache.org/viewvc/openjpa/trunk/openjpa-jdbc/src/main/java/org/apache/openjpa/jdbc/conf/JDBCConfiguration.java?rev=652913&r1=652912&r2=652913&view=diff
> >
> > ==============================================================================
> > ---
> > openjpa/trunk/openjpa-jdbc/src/main/java/org/apache/openjpa/jdbc/conf/JDBCConfiguration.java
> > (original)
> > +++
> > openjpa/trunk/openjpa-jdbc/src/main/java/org/apache/openjpa/jdbc/conf/JDBCConfiguration.java
> > Fri May  2 14:09:14 2008
> > @@ -18,6 +18,8 @@
> >  */
> > package org.apache.openjpa.jdbc.conf;
> >
> > +import java.util.Map;
> > +
> > import javax.sql.DataSource;
> >
> > import org.apache.openjpa.conf.OpenJPAConfiguration;
> > @@ -602,4 +604,23 @@
> >     * @see #getDataSource
> >     */
> >    public DataSource getDataSource2(StoreContext ctx);
> > +
> > +    /**
> > +     * Return QuerySQLCacheValue.
> > +     * @since 1.2.0
> > +     */
> > +    public QuerySQLCacheValue getQuerySQLCache();
> > +
> > +    /**
> > +     * Whether querySQLCache is enabled or not.
> > +     * @since 1.2.0
> > +     */
> > +    public boolean isQuerySQLCacheOn();
> > +
> > +    /**
> > +     * Return QuerySQLCacheInstance.
> > +     * @since 1.2.0
> > +     */
> > +    public Map getQuerySQLCacheInstance();
> > +
> > }
> >
> > Modified:
> > openjpa/trunk/openjpa-jdbc/src/main/java/org/apache/openjpa/jdbc/conf/JDBCConfigurationImpl.java
> > URL:
> > http://svn.apache.org/viewvc/openjpa/trunk/openjpa-jdbc/src/main/java/org/apache/openjpa/jdbc/conf/JDBCConfigurationImpl.java?rev=652913&r1=652912&r2=652913&view=diff
> >
> > ==============================================================================
> > ---
> > openjpa/trunk/openjpa-jdbc/src/main/java/org/apache/openjpa/jdbc/conf/JDBCConfigurationImpl.java
> > (original)
> > +++
> > openjpa/trunk/openjpa-jdbc/src/main/java/org/apache/openjpa/jdbc/conf/JDBCConfigurationImpl.java
> > Fri May  2 14:09:14 2008
> > @@ -20,6 +20,9 @@
> >
> > import java.sql.Connection;
> > import java.sql.ResultSet;
> > +import java.util.HashMap;
> > +import java.util.Map;
> > +
> > import javax.sql.DataSource;
> >
> > import org.apache.commons.lang.StringUtils;
> > @@ -82,6 +85,8 @@
> >    public ObjectValue mappingDefaultsPlugin;
> >    public PluginValue driverDataSourcePlugin;
> >    public MappingFactoryValue mappingFactoryPlugin;
> > +    public QuerySQLCacheValue querySQLCache;
> > +    private Map querySQLCacheInstance = new HashMap();
> >
> >    // used internally
> >    private String firstUser = null;
> > @@ -302,6 +307,9 @@
> >        seqPlugin.setDefault(JDBCSeqValue.ALIASES[0]);
> >        seqPlugin.setString(JDBCSeqValue.ALIASES[0]);
> >
> > +        querySQLCache = new QuerySQLCacheValue("jdbc.QuerySQLCache");
> > +        addValue(querySQLCache);
> > +
> >        // this static initializer is to get past a weird
> >        // ClassCircularityError that happens only under IBM's
> >        // JDK 1.3.1 on Linux from within the JRun ClassLoader;
> > @@ -856,4 +864,21 @@
> >                return true;
> >        return false;
> >    }
> > +
> > +    public void setQuerySQLCache(String querySQLCache) {
> > +        this.querySQLCache.setString(querySQLCache);
> > +    }
> > +
> > +    public QuerySQLCacheValue getQuerySQLCache() {
> > +        return querySQLCache;
> > +    }
> > +
> > +    public boolean isQuerySQLCacheOn() {
> > +        return querySQLCache.isSQLCacheOn();
> > +    }
> > +
> > +    public Map getQuerySQLCacheInstance() {
> > +        return querySQLCacheInstance;
> > +    }
> > +
> > }
> >
> > Added:
> > openjpa/trunk/openjpa-jdbc/src/main/java/org/apache/openjpa/jdbc/conf/QuerySQLCacheValue.java
> > URL:
> > http://svn.apache.org/viewvc/openjpa/trunk/openjpa-jdbc/src/main/java/org/apache/openjpa/jdbc/conf/QuerySQLCacheValue.java?rev=652913&view=auto
> >
> > ==============================================================================
> > ---
> > openjpa/trunk/openjpa-jdbc/src/main/java/org/apache/openjpa/jdbc/conf/QuerySQLCacheValue.java
> > (added)
> > +++
> > openjpa/trunk/openjpa-jdbc/src/main/java/org/apache/openjpa/jdbc/conf/QuerySQLCacheValue.java
> > Fri May  2 14:09:14 2008
> > @@ -0,0 +1,86 @@
> > +/*
> > + * Licensed to the Apache Software Foundation (ASF) under one
> > + * or more contributor license agreements.  See the NOTICE file
> > + * distributed with this work for additional information
> > + * regarding copyright ownership.  The ASF licenses this file
> > + * to you 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.jdbc.conf;
> > +
> > +import java.util.Collections;
> > +import java.util.Hashtable;
> > +import java.util.Map;
> > +import java.util.concurrent.ConcurrentHashMap;
> > +
> > +import org.apache.openjpa.lib.conf.Configurations;
> > +import org.apache.openjpa.lib.conf.PluginValue;
> > +import org.apache.openjpa.util.CacheMap;
> > +
> > +
> > +/**
> > + * A cache of sql queries.
> > + *
> > + * @since 1.2
> > + * @nojavadoc
> > + */
> > +public class QuerySQLCacheValue
> > +    extends PluginValue {
> > +
> > +    public static final String[] ALIASES = {
> > +        "true", CacheMap.class.getName(),
> > +        "all", ConcurrentHashMap.class.getName(),
> > +        "false", null,
> > +    };
> > +
> > +    public QuerySQLCacheValue(String prop) {
> > +        super(prop, true);
> > +        setAliases(ALIASES);
> > +        setDefault(ALIASES[0]);
> > +        setClassName(ALIASES[1]);
> > +    }
> > +
> > +    public boolean isSQLCacheOn() {
> > +        if (getClassName() == null)
> > +            return false;
> > +        return true;
> > +    }
> > +
> > +    public Object newInstance() {
> > +        // make sure map handles concurrency
> > +        String clsName = getClassName();
> > +        if (clsName == null)
> > +            return null;
> > +        Map map = null;
> > +
> > +        try {
> > +            // Use the "OpenJPA" classloader first...
> > +            map = (Map) Configurations.newInstance(clsName,
> > this.getClass()
> > +                    .getClassLoader());
> > +        } catch (Exception e) {
> > +            // If the "OpenJPA" classloader fails, then try the
> > classloader
> > +            // that was used to load java.util.Map...
> > +            map = (Map) Configurations.newInstance(clsName,
> > +                    Map.class.getClassLoader());
> > +        }
> > +        if (map != null
> > +                && !(map instanceof Hashtable)
> > +                && !(map instanceof CacheMap)
> > +                && !(map instanceof
> > +
> >  org.apache.openjpa.lib.util.concurrent.ConcurrentMap)
> > +                && !(map instanceof
> > java.util.concurrent.ConcurrentMap))
> > +            map = Collections.synchronizedMap(map);
> > +        return map;
> > +    }
> > +
> > +}
> >
> > Propchange:
> > openjpa/trunk/openjpa-jdbc/src/main/java/org/apache/openjpa/jdbc/conf/QuerySQLCacheValue.java
> >
> > ------------------------------------------------------------------------------
> >   svn:eol-style = native
> >
> > Modified:
> > openjpa/trunk/openjpa-jdbc/src/main/java/org/apache/openjpa/jdbc/kernel/JDBCStoreManager.java
> > URL:
> > http://svn.apache.org/viewvc/openjpa/trunk/openjpa-jdbc/src/main/java/org/apache/openjpa/jdbc/kernel/JDBCStoreManager.java?rev=652913&r1=652912&r2=652913&view=diff
> >
> > ==============================================================================
> > ---
> > openjpa/trunk/openjpa-jdbc/src/main/java/org/apache/openjpa/jdbc/kernel/JDBCStoreManager.java
> > (original)
> > +++
> > openjpa/trunk/openjpa-jdbc/src/main/java/org/apache/openjpa/jdbc/kernel/JDBCStoreManager.java
> > Fri May  2 14:09:14 2008
> > @@ -29,15 +29,20 @@
> > import java.util.Collections;
> > import java.util.HashSet;
> > import java.util.Iterator;
> > +import java.util.List;
> > +import java.util.Map;
> > import java.util.Set;
> > +
> > import javax.sql.DataSource;
> >
> > import org.apache.openjpa.event.OrphanedKeyAction;
> > import org.apache.openjpa.jdbc.conf.JDBCConfiguration;
> > +import org.apache.openjpa.jdbc.conf.QuerySQLCacheValue;
> > import org.apache.openjpa.jdbc.meta.ClassMapping;
> > import org.apache.openjpa.jdbc.meta.Discriminator;
> > import org.apache.openjpa.jdbc.meta.FieldMapping;
> > import org.apache.openjpa.jdbc.meta.ValueMapping;
> > +import org.apache.openjpa.jdbc.schema.Column;
> > import org.apache.openjpa.jdbc.sql.DBDictionary;
> > import org.apache.openjpa.jdbc.sql.JoinSyntaxes;
> > import org.apache.openjpa.jdbc.sql.Joins;
> > @@ -60,10 +65,12 @@
> > import org.apache.openjpa.lib.jdbc.DelegatingConnection;
> > import org.apache.openjpa.lib.jdbc.DelegatingPreparedStatement;
> > import org.apache.openjpa.lib.jdbc.DelegatingStatement;
> > +import org.apache.openjpa.lib.log.Log;
> > import org.apache.openjpa.lib.rop.MergedResultObjectProvider;
> > import org.apache.openjpa.lib.rop.ResultObjectProvider;
> > import org.apache.openjpa.lib.util.Localizer;
> > import org.apache.openjpa.meta.ClassMetaData;
> > +import org.apache.openjpa.meta.FetchGroup;
> > import org.apache.openjpa.meta.FieldMetaData;
> > import org.apache.openjpa.meta.JavaTypes;
> > import org.apache.openjpa.meta.ValueStrategies;
> > @@ -99,7 +106,11 @@
> >
> >    // track the pending statements so we can cancel them
> >    private Set _stmnts = Collections.synchronizedSet(new HashSet());
> > -
> > +
> > +    private Map _sqlCache = null;
> > +    private boolean _isQuerySQLCache = true;
> > +    private static final Object _nullCacheValue = new Object();
> > +
> >    public StoreContext getContext() {
> >        return _ctx;
> >    }
> > @@ -125,6 +136,9 @@
> >
> >        if (_conf.getUpdateManagerInstance().orderDirty())
> >            ctx.setOrderDirtyObjects(true);
> > +
> > +        _sqlCache = _conf.getQuerySQLCacheInstance();
> > +        _isQuerySQLCache = _conf.isQuerySQLCacheOn();
> >    }
> >
> >    public JDBCConfiguration getConfiguration() {
> > @@ -402,13 +416,86 @@
> >    private Result getInitializeStateResult(OpenJPAStateManager sm,
> >        ClassMapping mapping, JDBCFetchConfiguration fetch, int subs)
> >        throws SQLException {
> > +        List params = new ArrayList();
> > +        Select sel = newSelect(sm, mapping, fetch, subs, params);
> > +        if (sel == null) return null;
> > +        return sel.execute(this, fetch, params);
> > +    }
> > +
> > +    private Select newSelect(OpenJPAStateManager sm,
> > +        ClassMapping mapping, JDBCFetchConfiguration fetch, int subs,
> > +        List params) {
> > +        if (!_isQuerySQLCache)
> > +            return newSelect(sm, mapping, fetch, subs);
> > +
> > +        Map<SelectKey, Select> selectImplCacheMap =
> > +            getCacheMapFromQuerySQLCache(JDBCStoreManager.class);
> > +        JDBCFetchConfiguration fetchClone = new
> > JDBCFetchConfigurationImpl();
> > +        fetchClone.copy(fetch);
> > +        SelectKey selKey = new SelectKey(mapping, null, fetchClone);
> > +        Select sel = null;
> > +        boolean found = true;
> > +        Object obj = selectImplCacheMap.get(selKey);
> > +        if (obj == null) {
> > +            synchronized (selectImplCacheMap) {
> > +                obj = selectImplCacheMap.get(selKey);
> > +                if (obj == null) {
> > +                    // Not found in cache, create a new select
> > +                    obj = newSelect(sm, mapping, fetch, subs);
> > +                    found = false;
> > +                }
> > +
> > +                if (obj == null) {
> > +                    // If the generated SelectImpl is null, store a
> > generic
> > +                    // known object in the cache as a placeholder. Some
> > map
> > +                    // implementations do not allow null values.
> > +                    obj = _nullCacheValue;
> > +                    found = false;
> > +                }
> > +                else if (obj != _nullCacheValue)
> > +                {
> > +                    sel = (Select)obj;
> > +                    if (sel.getSQL() == null) {
> > +                        sel.setSQL(this, fetch);
> > +                        found = false;
> > +                    }
> > +                }
> > +                if (!found) {
> > +                    addToSqlCache(selectImplCacheMap, selKey, obj);
> > +                }
> > +            }
> > +        }
> > +
> > +        if (obj != null && obj != _nullCacheValue)
> > +            sel = (Select) obj;
> > +
> > +        Log log = _conf.getLog(JDBCConfiguration.LOG_JDBC);
> > +        if (log.isTraceEnabled()) {
> > +            if (!found)
> > +                log.trace(_loc.get("cache-missed", mapping,
> > this.getClass()));
> > +            else
> > +                log.trace(_loc.get("cache-hit", mapping,
> > this.getClass()));
> > +        }
> > +
> > +        if (sel == null)
> > +            return null;
> > +
> > +        Object oid = sm.getObjectId();
> > +        Column[] cols = mapping.getPrimaryKeyColumns();
> > +        sel.wherePrimaryKey(mapping, cols, cols, oid, this,
> > +               null, null, params);
> > +        return sel;
> > +    }
> > +
> > +    protected Select newSelect(OpenJPAStateManager sm,
> > +        ClassMapping mapping, JDBCFetchConfiguration fetch, int subs) {
> >        Select sel = _sql.newSelect();
> >        if (!select(sel, mapping, subs, sm, null, fetch,
> >            JDBCFetchConfiguration.EAGER_JOIN, true, false))
> >            return null;
> >        sel.wherePrimaryKey(sm.getObjectId(), mapping, this);
> >        sel.setExpectedResultCount(1, false);
> > -        return sel.execute(this, fetch);
> > +        return sel;
> >    }
> >
> >    /**
> > @@ -1419,4 +1506,163 @@
> >            }
> >        }
> >    }
> > +
> > +    public Map getCacheMapFromQuerySQLCache(Object key) {
> > +        synchronized(_sqlCache) {
> > +            //sqlCache is a map of map
> > +            Map cacheMap = (Map)_sqlCache.get(key);
> > +            if (cacheMap == null) {
> > +                cacheMap = createSQLCache();
> > +                _sqlCache.put(key, cacheMap);
> > +            }
> > +            return cacheMap;
> > +        }
> > +    }
> > +
> > +    public void addToSqlCache(Map cacheMap, Object key, Object value) {
> > +        cacheMap.put(key, value);
> > +    }
> > +
> > +    public Map createSQLCache() {
> > +        QuerySQLCacheValue querySQLCache = _conf.getQuerySQLCache();
> > +        return (Map)querySQLCache.newInstance();
> > +    }
> > +
> > +    public boolean isQuerySQLCacheOn() {
> > +        return _isQuerySQLCache;
> > +    }
> > +
> > +    public Map getQuerySQLCache() {
> > +        return _sqlCache;
> > +    }
> > +
> > +    public static class SelectKey {
> > +        public ClassMapping mapping;
> > +        public FieldMapping fm;
> > +        public JDBCFetchConfiguration fetch;
> > +
> > +        public SelectKey (ClassMapping mapping, FieldMapping fm,
> > +            JDBCFetchConfiguration fetch) {
> > +            this.mapping = mapping;
> > +            this.fm = fm;
> > +            this.fetch = fetch;
> > +        }
> > +
> > +        public boolean equals(Object o) {
> > +            if (this == o) return true;
> > +            if (o == null || getClass() != o.getClass()) return false;
> > +
> > +            SelectKey selectKey = (SelectKey) o;
> > +            if (fetch != null ? !equals(fetch, selectKey.fetch) :
> > +                selectKey.fetch != null) return false;
> > +            if (mapping != null ? !mapping.equals(selectKey.mapping) :
> > +                selectKey.mapping != null) return false;
> > +            if (fm != null ? !fm.equals(selectKey.fm) :
> > +                selectKey.fm != null) return false;
> > +            return true;
> > +        }
> > +
> > +        public boolean equals(JDBCFetchConfiguration fetch1,
> > +               JDBCFetchConfiguration fetch2) {
> > +            if (fetch1 == fetch2)
> > +               return true;
> > +
> > +            if (fetch1.getIsolation() != fetch2.getIsolation())
> > +               return false;
> > +            if (fetch1.getFetchDirection() !=
> > fetch2.getFetchDirection())
> > +               return false;
> > +            if (fetch1.getEagerFetchMode() !=
> > fetch2.getEagerFetchMode())
> > +               return false;
> > +            if (fetch1.getSubclassFetchMode() !=
> > fetch2.getSubclassFetchMode())
> > +               return false;
> > +            if (fetch1.getJoinSyntax() != fetch2.getJoinSyntax())
> > +               return false;
> > +            Set joins1 = fetch1.getJoins();
> > +            Set joins2 = fetch2.getJoins();
> > +            if (joins1 != null ? !joins1.equals(joins2) : joins2 !=
> > null)
> > +                return false;
> > +
> > +            if (fetch1.getMaxFetchDepth() != fetch2.getMaxFetchDepth())
> > +               return false;
> > +            if (fetch1.getReadLockLevel() != fetch2.getReadLockLevel())
> > +               return false;
> > +            if (fetch1.getWriteLockLevel() !=
> > fetch2.getWriteLockLevel())
> > +               return false;
> > +
> > +            boolean sameFetchGroup = false;
> > +            boolean hasFetchGroupAll =
> > ((JDBCFetchConfigurationImpl)fetch1).
> > +               hasFetchGroupAll();
> > +            boolean hasFetchGroupAll1 =
> > ((JDBCFetchConfigurationImpl)fetch2).
> > +               hasFetchGroupAll();
> > +            if (hasFetchGroupAll && hasFetchGroupAll1)
> > +                sameFetchGroup = true;
> > +            else if (!hasFetchGroupAll && !hasFetchGroupAll1){
> > +                boolean hasFetchGroupDefault =
> > +
> > ((JDBCFetchConfigurationImpl)fetch1).hasFetchGroupDefault();
> > +                boolean hasFetchGroupDefault1 =
> > +
> > ((JDBCFetchConfigurationImpl)fetch2).hasFetchGroupDefault();
> > +                if (hasFetchGroupDefault && hasFetchGroupDefault1)
> > +                    sameFetchGroup = true;
> > +            }
> > +
> > +            if (!sameFetchGroup) {
> > +                Set fetchGroups = fetch1.getFetchGroups();
> > +                Set fetchGroups1 = fetch2.getFetchGroups();
> > +                if (fetchGroups != null ?
> > !fetchGroups.equals(fetchGroups1) :
> > +                       fetchGroups1 != null)
> > +                    return false;
> > +            }
> > +
> > +            Set fields = fetch1.getFields();
> > +            Set fields1 = fetch2.getFields();
> > +            int size = fields.size();
> > +            int size1 = fields1.size();
> > +            if (size == 0 && size1 == 0)
> > +                return true;
> > +            else if (size != size1)
> > +                return false;
> > +
> > +            if (fields != null ? !fields.equals(fields1) : fields1 !=
> > null)
> > +                return false;
> > +
> > +            return true;
> > +        }
> > +
> > +
> > +        public int hashCode() {
> > +            int result = 0;
> > +            result = 31 * result + (mapping != null ?
> > mapping.hashCode() : 0);
> > +            result = 31 * result + (fm != null ? fm.hashCode() : 0);
> > +            result = 31 * result + fetch.getIsolation();
> > +            result = 31 * result + fetch.getFetchDirection();
> > +            result = 31 * result + fetch.getEagerFetchMode();
> > +            result = 31 * result + fetch.getSubclassFetchMode();
> > +            result = 31 * result + fetch.getJoinSyntax();
> > +            Set joins = fetch.getJoins();
> > +            result = 31 * result + (joins != null ? joins.hashCode() :
> > 0);
> > +
> > +            result = 31 * result + fetch.getMaxFetchDepth();
> > +            result = 31 * result + fetch.getReadLockLevel();
> > +            result = 31 * result + fetch.getWriteLockLevel();
> > +
> > +            if (((JDBCFetchConfigurationImpl)fetch).hasFetchGroupAll())
> > +               result = 31 * result + FetchGroup.NAME_ALL.hashCode();
> > +            else {
> > +                Set fetchGroups = fetch.getFetchGroups();
> > +                if
> > (((JDBCFetchConfigurationImpl)fetch).hasFetchGroupDefault()
> > +                       && fetchGroups != null && fetchGroups.size() ==
> > 1)
> > +                    result = 31 * result +
> > FetchGroup.NAME_DEFAULT.hashCode();
> > +                else {
> > +                    result = 31 * result + (fetchGroups != null &&
> > +                        fetchGroups.size() > 0 ?
> > +                        fetchGroups.hashCode() : 0);
> > +                }
> > +            }
> > +            Set fields = fetch.getFields();
> > +               result = 31 * result + (fields != null &&  fields.size()
> > > 0 ?
> > +                       fields.hashCode() : 0);
> > +
> > +            return result;
> > +        }
> > +    }
> > }
> >
> > Modified:
> > openjpa/trunk/openjpa-jdbc/src/main/java/org/apache/openjpa/jdbc/meta/strats/RelationFieldStrategy.java
> > URL:
> > http://svn.apache.org/viewvc/openjpa/trunk/openjpa-jdbc/src/main/java/org/apache/openjpa/jdbc/meta/strats/RelationFieldStrategy.java?rev=652913&r1=652912&r2=652913&view=diff
> >
> > ==============================================================================
> > ---
> > openjpa/trunk/openjpa-jdbc/src/main/java/org/apache/openjpa/jdbc/meta/strats/RelationFieldStrategy.java
> > (original)
> > +++
> > openjpa/trunk/openjpa-jdbc/src/main/java/org/apache/openjpa/jdbc/meta/strats/RelationFieldStrategy.java
> > Fri May  2 14:09:14 2008
> > @@ -19,11 +19,16 @@
> > package org.apache.openjpa.jdbc.meta.strats;
> >
> > import java.sql.SQLException;
> > +import java.util.ArrayList;
> > import java.util.HashMap;
> > +import java.util.List;
> > import java.util.Map;
> >
> > +import org.apache.openjpa.jdbc.conf.JDBCConfiguration;
> > import org.apache.openjpa.jdbc.kernel.JDBCFetchConfiguration;
> > +import org.apache.openjpa.jdbc.kernel.JDBCFetchConfigurationImpl;
> > import org.apache.openjpa.jdbc.kernel.JDBCStore;
> > +import org.apache.openjpa.jdbc.kernel.JDBCStoreManager;
> > import org.apache.openjpa.jdbc.meta.ClassMapping;
> > import org.apache.openjpa.jdbc.meta.Embeddable;
> > import org.apache.openjpa.jdbc.meta.FieldMapping;
> > @@ -38,12 +43,14 @@
> > import org.apache.openjpa.jdbc.schema.Table;
> > import org.apache.openjpa.jdbc.sql.DBDictionary;
> > import org.apache.openjpa.jdbc.sql.Joins;
> > +import org.apache.openjpa.jdbc.sql.LogicalUnion;
> > import org.apache.openjpa.jdbc.sql.Result;
> > import org.apache.openjpa.jdbc.sql.Row;
> > import org.apache.openjpa.jdbc.sql.RowManager;
> > import org.apache.openjpa.jdbc.sql.SQLBuffer;
> > import org.apache.openjpa.jdbc.sql.Select;
> > import org.apache.openjpa.jdbc.sql.SelectExecutor;
> > +import org.apache.openjpa.jdbc.sql.SelectImpl;
> > import org.apache.openjpa.jdbc.sql.Union;
> > import org.apache.openjpa.kernel.OpenJPAStateManager;
> > import org.apache.openjpa.lib.log.Log;
> > @@ -55,6 +62,7 @@
> > import org.apache.openjpa.util.MetaDataException;
> > import org.apache.openjpa.util.OpenJPAId;
> > import org.apache.openjpa.util.UnsupportedException;
> > +
> > import serp.util.Numbers;
> >
> > /**
> > @@ -579,9 +587,97 @@
> >        final int subs = field.getSelectSubclasses();
> >        final Joins[] resJoins = new Joins[rels.length];
> >
> > -        // select related mapping columns; joining from the related
> > type
> > -        // back to our fk table if not an inverse mapping (in which
> > case we
> > -        // can just make sure the inverse cols == our pk values)
> > +        //cache union for field here
> > +        //select data for this sm
> > +        Union union = null;
> > +        SelectImpl sel = null;
> > +        List parmList = null;
> > +
> > +        if (!((JDBCStoreManager)store).isQuerySQLCacheOn())
> > +            union = newUnion(sm, store, fetch, rels, subs, resJoins);
> > +        else {
> > +            Map<JDBCStoreManager.SelectKey, Object[]>
> > relationFieldUnionCache =
> > +                ((JDBCStoreManager)store).getCacheMapFromQuerySQLCache(
> > +                RelationFieldStrategy.class);
> > +            boolean found = true;
> > +            JDBCFetchConfiguration fetchClone = new
> > JDBCFetchConfigurationImpl();
> > +            fetchClone.copy(fetch);
> > +            JDBCStoreManager.SelectKey selKey =
> > +                new JDBCStoreManager.SelectKey(null, field, fetch);
> > +            Object[] obj = relationFieldUnionCache.get(selKey);
> > +            if (obj != null) {
> > +                union = (Union) obj[0];
> > +                resJoins[0] = (Joins)obj[1];
> > +            } else {
> > +                synchronized(relationFieldUnionCache) {
> > +                    obj = relationFieldUnionCache.get(selKey);
> > +                    if (obj != null) {
> > +                        union = (Union) obj[0];
> > +                        resJoins[0] = (Joins) obj[1];
> > +                    } else {
> > +                        // select related mapping columns; joining from
> > the
> > +                        // related type back to our fk table if not an
> > inverse
> > +                        // mapping (in which case we can just make sure
> > the
> > +                        // inverse cols == our pk values)
> > +                        union = newUnion(sm, store, fetch, rels, subs,
> > +                                resJoins);
> > +                        found = false;
> > +                    }
> > +                    sel =
> > ((LogicalUnion.UnionSelect)union.getSelects()[0]).
> > +                        getDelegate();
> > +                    SQLBuffer buf = sel.getSQL();
> > +                    if (buf == null) {
> > +                       ((SelectImpl)sel).setSQL(store, fetch);
> > +                        found = false;
> > +                    }
> > +
> > +                    // only cache the union when elems length is 1 for
> > now
> > +                    if (!found && rels.length == 1) {
> > +                        Object[] obj1 = new Object[2];
> > +                        obj1[0] = union;
> > +                        obj1[1] = resJoins[0];
> > +                        ((JDBCStoreManager)store).addToSqlCache(
> > +                            relationFieldUnionCache, selKey, obj1);
> > +                    }
> > +                }
> > +            }
> > +            Log log = store.getConfiguration().
> > +                getLog(JDBCConfiguration.LOG_JDBC);
> > +            if (log.isTraceEnabled()){
> > +                if (found)
> > +                    log.trace(_loc.get("cache-hit", field,
> > this.getClass()));
> > +                else
> > +                    log.trace(_loc.get("cache-missed", field,
> > this.getClass()));
> > +            }
> > +
> > +            parmList = new ArrayList();
> > +            ClassMapping mapping = field.getDefiningMapping();
> > +            Object oid = sm.getObjectId();
> > +            Column[] cols = mapping.getPrimaryKeyColumns();
> > +            if (sel == null)
> > +                sel =
> > ((LogicalUnion.UnionSelect)union.getSelects()[0]).
> > +                getDelegate();
> > +
> > +            sel.wherePrimaryKey(mapping, cols, cols, oid, store,
> > +               null, null, parmList);
> > +        }
> > +
> > +        Result res = union.execute(store, fetch, parmList);
> > +        try {
> > +            Object val = null;
> > +            if (res.next())
> > +                val = res.load(rels[res.indexOf()], store, fetch,
> > +                    resJoins[res.indexOf()]);
> > +            sm.storeObject(field.getIndex(), val);
> > +        } finally {
> > +            res.close();
> > +        }
> > +    }
> > +
> > +    protected Union newUnion(final OpenJPAStateManager sm,
> > +        final JDBCStore store, final JDBCFetchConfiguration fetch,
> > +        final ClassMapping[] rels, final int subs,
> > +        final Joins[] resJoins) {
> >        Union union = store.getSQLFactory().newUnion(rels.length);
> >        union.setExpectedResultCount(1, false);
> >        if (fetch.getSubclassFetchMode(field.getTypeMapping())
> > @@ -602,17 +698,7 @@
> >                    resJoins[idx]);
> >            }
> >        });
> > -
> > -        Result res = union.execute(store, fetch);
> > -        try {
> > -            Object val = null;
> > -            if (res.next())
> > -                val = res.load(rels[res.indexOf()], store, fetch,
> > -                    resJoins[res.indexOf()]);
> > -            sm.storeObject(field.getIndex(), val);
> > -        } finally {
> > -            res.close();
> > -        }
> > +        return union;
> >    }
> >
> >    public Object toDataStoreValue(Object val, JDBCStore store) {
> >
> > Modified:
> > openjpa/trunk/openjpa-jdbc/src/main/java/org/apache/openjpa/jdbc/meta/strats/StoreCollectionFieldStrategy.java
> > URL:
> > http://svn.apache.org/viewvc/openjpa/trunk/openjpa-jdbc/src/main/java/org/apache/openjpa/jdbc/meta/strats/StoreCollectionFieldStrategy.java?rev=652913&r1=652912&r2=652913&view=diff
> >
> > ==============================================================================
> > ---
> > openjpa/trunk/openjpa-jdbc/src/main/java/org/apache/openjpa/jdbc/meta/strats/StoreCollectionFieldStrategy.java
> > (original)
> > +++
> > openjpa/trunk/openjpa-jdbc/src/main/java/org/apache/openjpa/jdbc/meta/strats/StoreCollectionFieldStrategy.java
> > Fri May  2 14:09:14 2008
> > @@ -22,21 +22,29 @@
> > import java.util.ArrayList;
> > import java.util.Collection;
> > import java.util.HashMap;
> > +import java.util.List;
> > import java.util.Map;
> >
> > +import org.apache.openjpa.jdbc.conf.JDBCConfiguration;
> > import org.apache.openjpa.jdbc.kernel.JDBCFetchConfiguration;
> > +import org.apache.openjpa.jdbc.kernel.JDBCFetchConfigurationImpl;
> > import org.apache.openjpa.jdbc.kernel.JDBCStore;
> > +import org.apache.openjpa.jdbc.kernel.JDBCStoreManager;
> > import org.apache.openjpa.jdbc.meta.ClassMapping;
> > import org.apache.openjpa.jdbc.meta.FieldMapping;
> > import org.apache.openjpa.jdbc.meta.FieldStrategy;
> > import org.apache.openjpa.jdbc.schema.Column;
> > import org.apache.openjpa.jdbc.schema.ForeignKey;
> > import org.apache.openjpa.jdbc.sql.Joins;
> > +import org.apache.openjpa.jdbc.sql.LogicalUnion;
> > import org.apache.openjpa.jdbc.sql.Result;
> > import org.apache.openjpa.jdbc.sql.Select;
> > import org.apache.openjpa.jdbc.sql.SelectExecutor;
> > +import org.apache.openjpa.jdbc.sql.SelectImpl;
> > import org.apache.openjpa.jdbc.sql.Union;
> > import org.apache.openjpa.kernel.OpenJPAStateManager;
> > +import org.apache.openjpa.lib.log.Log;
> > +import org.apache.openjpa.lib.util.Localizer;
> > import org.apache.openjpa.meta.JavaTypes;
> > import org.apache.openjpa.util.ChangeTracker;
> > import org.apache.openjpa.util.Id;
> > @@ -55,6 +63,9 @@
> > public abstract class StoreCollectionFieldStrategy
> >    extends ContainerFieldStrategy {
> >
> > +    private static final Localizer _loc = Localizer.forPackage
> > +        (StoreCollectionFieldStrategy.class);
> > +
> >    /**
> >     * Return the foreign key used to join to the owning field for the
> > given
> >     * element mapping from {@link #getIndependentElementMappings} (or
> > null).
> > @@ -445,19 +456,83 @@
> >            return;
> >        }
> >
> > +        //cache union for field here
> >        // select data for this sm
> > +        boolean found = true;
> >        final ClassMapping[] elems = getIndependentElementMappings(true);
> >        final Joins[] resJoins = new Joins[Math.max(1, elems.length)];
> > -        Union union = store.getSQLFactory().newUnion
> > -            (Math.max(1, elems.length));
> > -        union.select(new Union.Selector() {
> > -            public void select(Select sel, int idx) {
> > -                ClassMapping elem = (elems.length == 0) ? null :
> > elems[idx];
> > -                resJoins[idx] = selectAll(sel, elem, sm, store, fetch,
> > -                    JDBCFetchConfiguration.EAGER_PARALLEL);
> > +        List parmList = null;
> > +        Union union = null;
> > +        SelectImpl sel = null;
> > +        Map<JDBCStoreManager.SelectKey, Object[]>
> > storeCollectionUnionCache = null;
> > +        JDBCStoreManager.SelectKey selKey = null;
> > +        if (!((JDBCStoreManager)store).isQuerySQLCacheOn())
> > +            union = newUnion(sm, store, fetch, elems, resJoins);
> > +        else {
> > +            parmList = new ArrayList();
> > +            JDBCFetchConfiguration fetchClone = new
> > JDBCFetchConfigurationImpl();
> > +            fetchClone.copy(fetch);
> > +
> > +            // to specify the type so that no cast is needed
> > +            storeCollectionUnionCache = ((JDBCStoreManager)store).
> > +
> >  getCacheMapFromQuerySQLCache(StoreCollectionFieldStrategy.class);
> > +            selKey =
> > +                new JDBCStoreManager.SelectKey(null, field,
> > fetchClone);
> > +            Object[] objs = storeCollectionUnionCache.get(selKey);
> > +            if (objs != null) {
> > +                union = (Union) objs[0];
> > +                resJoins[0] = (Joins) objs[1];
> >            }
> > -        });
> > +            else {
> > +                synchronized(storeCollectionUnionCache) {
> > +                    objs = storeCollectionUnionCache.get(selKey);
> > +                    if (objs == null) {
> > +                        // select data for this sm
> > +                        union = newUnion(sm, store, fetch, elems,
> > resJoins);
> > +                        found = false;
> > +                    } else {
> > +                        union = (Union) objs[0];
> > +                        resJoins[0] = (Joins) objs[1];
> > +                    }
> > +
> > +                    sel =
> > ((LogicalUnion.UnionSelect)union.getSelects()[0]).
> > +                        getDelegate();
> > +                    if (sel.getSQL() == null) {
> > +                       ((SelectImpl)sel).setSQL(store, fetch);
> > +                        found = false;
> > +                    }
> > +
> > +                    // only cache the union when elems length is 1 for
> > now
> > +                    if (!found && elems.length == 1) {
> > +                        Object[] objs1 = new Object[2];
> > +                        objs1[0] = union;
> > +                        objs1[1] = resJoins[0];
> > +                        ((JDBCStoreManager)store).addToSqlCache(
> > +                            storeCollectionUnionCache, selKey, objs1);
> > +                     }
> > +                }
> > +            }
> > +
> > +            Log log = store.getConfiguration().
> > +                getLog(JDBCConfiguration.LOG_JDBC);
> > +            if (log.isTraceEnabled()) {
> > +                if (found)
> > +                    log.trace(_loc.get("cache-hit", field,
> > this.getClass()));
> > +                else
> > +                    log.trace(_loc.get("cache-missed", field,
> > this.getClass()));
> > +            }
> > +
> > +            ClassMapping mapping = field.getDefiningMapping();
> > +            Object oid = sm.getObjectId();
> > +            Column[] cols = mapping.getPrimaryKeyColumns();
> > +            if (sel == null)
> > +                sel =
> > ((LogicalUnion.UnionSelect)union.getSelects()[0]).
> > +                getDelegate();
> >
> > +            sel.wherePrimaryKey(mapping, cols, cols, oid, store,
> > +                       null, null, parmList);
> > +        }
> > +
> >        // create proxy
> >        Object coll;
> >        ChangeTracker ct = null;
> > @@ -470,14 +545,14 @@
> >        }
> >
> >        // load values
> > -        Result res = union.execute(store, fetch);
> > +        Result res = union.execute(store, fetch, parmList);
> >        try {
> >            int seq = -1;
> >            while (res.next()) {
> >                if (ct != null && field.getOrderColumn() != null)
> >                    seq = res.getInt(field.getOrderColumn());
> > -                add(store, coll, loadElement(sm, store, fetch, res,
> > -                    resJoins[res.indexOf()]));
> > +                       add(store, coll, loadElement(sm, store, fetch,
> > res,
> > +                       resJoins[res.indexOf()]));
> >            }
> >            if (ct != null && field.getOrderColumn() != null)
> >                ct.setNextSequence(seq + 1);
> > @@ -493,6 +568,21 @@
> >            sm.storeObject(field.getIndex(), coll);
> >    }
> >
> > +    protected Union newUnion(final OpenJPAStateManager sm, final
> > JDBCStore store,
> > +        final JDBCFetchConfiguration fetch, final ClassMapping[] elems,
> > +        final Joins[] resJoins) {
> > +        Union union = store.getSQLFactory().newUnion
> > +        (Math.max(1, elems.length));
> > +        union.select(new Union.Selector() {
> > +            public void select(Select sel, int idx) {
> > +                ClassMapping elem = (elems.length == 0) ? null :
> > elems[idx];
> > +                resJoins[idx] = selectAll(sel, elem, sm, store, fetch,
> > +                        JDBCFetchConfiguration.EAGER_PARALLEL);
> > +            }
> > +        });
> > +        return union;
> > +    }
> > +
> >    /**
> >     * Select data for loading, starting in field table.
> >     */
> >
> > Modified:
> > openjpa/trunk/openjpa-jdbc/src/main/java/org/apache/openjpa/jdbc/sql/LogicalUnion.java
> > URL:
> > http://svn.apache.org/viewvc/openjpa/trunk/openjpa-jdbc/src/main/java/org/apache/openjpa/jdbc/sql/LogicalUnion.java?rev=652913&r1=652912&r2=652913&view=diff
> >
> > ==============================================================================
> > ---
> > openjpa/trunk/openjpa-jdbc/src/main/java/org/apache/openjpa/jdbc/sql/LogicalUnion.java
> > (original)
> > +++
> > openjpa/trunk/openjpa-jdbc/src/main/java/org/apache/openjpa/jdbc/sql/LogicalUnion.java
> > Fri May  2 14:09:14 2008
> > @@ -202,20 +202,32 @@
> >    }
> >
> >    public Result execute(JDBCStore store, JDBCFetchConfiguration fetch)
> > +            throws SQLException {
> > +        return execute(store, fetch, null);
> > +    }
> > +
> > +    public Result execute(JDBCStore store, JDBCFetchConfiguration
> > fetch,
> > +        int lockLevel)
> > +        throws SQLException {
> > +        return execute(store, fetch, lockLevel, null);
> > +    }
> > +
> > +    public Result execute(JDBCStore store, JDBCFetchConfiguration
> > fetch,
> > +        List params)
> >        throws SQLException {
> >        if (fetch == null)
> >            fetch = store.getFetchConfiguration();
> > -        return execute(store, fetch, fetch.getReadLockLevel());
> > +        return execute(store, fetch, fetch.getReadLockLevel(), params);
> >    }
> >
> >    public Result execute(JDBCStore store, JDBCFetchConfiguration fetch,
> > -        int lockLevel)
> > +        int lockLevel, List params)
> >        throws SQLException {
> >        if (fetch == null)
> >            fetch = store.getFetchConfiguration();
> >
> >        if (sels.length == 1) {
> > -            Result res = sels[0].execute(store, fetch, lockLevel);
> > +            Result res = sels[0].execute(store, fetch, lockLevel,
> > params);
> >            ((AbstractResult) res).setBaseMapping(mappings[0]);
> >            return res;
> >        }
> > @@ -224,7 +236,7 @@
> >            AbstractResult res;
> >            for (int i = 0; i < sels.length; i++) {
> >                res = (AbstractResult) sels[i].execute(store, fetch,
> > -                    lockLevel);
> > +                    lockLevel, params);
> >                res.setBaseMapping(mappings[i]);
> >                res.setIndexOf(i);
> >
> > @@ -256,7 +268,7 @@
> >            List l;
> >            for (int i = 0; i < res.length; i++) {
> >                res[i] = (AbstractResult) sels[i].execute(store, fetch,
> > -                    lockLevel);
> > +                    lockLevel, params);
> >                res[i].setBaseMapping(mappings[i]);
> >                res[i].setIndexOf(i);
> >
> > @@ -303,7 +315,7 @@
> >    /**
> >     * A select that is part of a logical union.
> >     */
> > -    protected class UnionSelect
> > +    public class UnionSelect
> >        implements Select {
> >
> >        protected final SelectImpl sel;
> > @@ -396,6 +408,18 @@
> >            return sel.getCount(store);
> >        }
> >
> > +        public Result execute(JDBCStore store, JDBCFetchConfiguration
> > fetch,
> > +            List params)
> > +            throws SQLException {
> > +            return sel.execute(store, fetch, params);
> > +        }
> > +
> > +        public Result execute(JDBCStore store, JDBCFetchConfiguration
> > fetch,
> > +            int lockLevel, List params)
> > +            throws SQLException {
> > +            return sel.execute(store, fetch, lockLevel, params);
> > +        }
> > +
> >        public Result execute(JDBCStore store, JDBCFetchConfiguration
> > fetch)
> >            throws SQLException {
> >            return sel.execute(store, fetch);
> > @@ -406,7 +430,7 @@
> >            throws SQLException {
> >            return sel.execute(store, fetch, lockLevel);
> >        }
> > -
> > +
> >        public List getSubselects() {
> >            return Collections.EMPTY_LIST;
> >        }
> > @@ -475,6 +499,14 @@
> >            return sel.getHaving();
> >        }
> >
> > +        public SQLBuffer getSQL() {
> > +            return sel.getSQL();
> > +        }
> > +
> > +        public void setSQL(JDBCStore store, JDBCFetchConfiguration
> > fetch) {
> > +            sel.setSQL(store, fetch);
> > +        }
> > +
> >        public void addJoinClassConditions() {
> >            sel.addJoinClassConditions();
> >        }
> > @@ -717,6 +749,15 @@
> >            JDBCStore store) {
> >            sel.wherePrimaryKey(oid, mapping, store);
> >        }
> > +
> > +        public int wherePrimaryKey(ClassMapping mapping, Column[]
> > toCols,
> > +            Column[] fromCols, Object oid, JDBCStore store, PathJoins
> > pj,
> > +            SQLBuffer buf, List parmList) {
> > +            return sel.wherePrimaryKey(mapping, toCols, fromCols, oid,
> > store, pj,
> > +                buf, parmList);
> > +        }
> > +
> > +
> >
> >        public void whereForeignKey(ForeignKey fk, Object oid,
> >            ClassMapping mapping, JDBCStore store) {
> >
> > Modified:
> > openjpa/trunk/openjpa-jdbc/src/main/java/org/apache/openjpa/jdbc/sql/SQLBuffer.java
> > URL:
> > http://svn.apache.org/viewvc/openjpa/trunk/openjpa-jdbc/src/main/java/org/apache/openjpa/jdbc/sql/SQLBuffer.java?rev=652913&r1=652912&r2=652913&view=diff
> >
> > ==============================================================================
> > ---
> > openjpa/trunk/openjpa-jdbc/src/main/java/org/apache/openjpa/jdbc/sql/SQLBuffer.java
> > (original)
> > +++
> > openjpa/trunk/openjpa-jdbc/src/main/java/org/apache/openjpa/jdbc/sql/SQLBuffer.java
> > Fri May  2 14:09:14 2008
> > @@ -450,9 +450,19 @@
> >     * the SQL in this buffer.
> >     */
> >    public PreparedStatement prepareStatement(Connection conn, int
> > rsType,
> > +        int rsConcur, List parms)
> > +        throws SQLException {
> > +        return prepareStatement(conn, null, rsType, rsConcur, parms);
> > +    }
> > +
> > +    /**
> > +     * Create and populate the parameters of a prepared statement using
> > +     * the SQL in this buffer.
> > +     */
> > +    public PreparedStatement prepareStatement(Connection conn, int
> > rsType,
> >        int rsConcur)
> >        throws SQLException {
> > -        return prepareStatement(conn, null, rsType, rsConcur);
> > +        return prepareStatement(conn, rsType, rsConcur, null);
> >    }
> >
> >    /**
> > @@ -462,6 +472,16 @@
> >    public PreparedStatement prepareStatement(Connection conn,
> >        JDBCFetchConfiguration fetch, int rsType, int rsConcur)
> >        throws SQLException {
> > +        return prepareStatement(conn, fetch, rsType, rsConcur, null);
> > +    }
> > +
> > +    /**
> > +     * Create and populate the parameters of a prepred statement using
> > the
> > +     * SQL in this buffer and the given fetch configuration.
> > +     */
> > +    public PreparedStatement prepareStatement(Connection conn,
> > +        JDBCFetchConfiguration fetch, int rsType, int rsConcur, List
> > parms)
> > +        throws SQLException {
> >        if (rsType == -1 && fetch == null)
> >            rsType = ResultSet.TYPE_FORWARD_ONLY;
> >        else if (rsType == -1)
> > @@ -476,7 +496,7 @@
> >        else
> >            stmnt = conn.prepareStatement(getSQL(), rsType, rsConcur);
> >        try {
> > -            setParameters(stmnt);
> > +            setParameters(stmnt, parms);
> >            if (fetch != null) {
> >                if (fetch.getFetchBatchSize() > 0)
> >                    stmnt.setFetchSize(fetch.getFetchBatchSize());
> > @@ -559,13 +579,25 @@
> >     */
> >    public void setParameters(PreparedStatement ps)
> >        throws SQLException {
> > -        if (_params == null)
> > +        setParameters(ps, null);
> > +    }
> > +
> > +    /**
> > +     * Populate the parameters of an existing PreparedStatement
> > +     * with values from this buffer.
> > +     */
> > +    public void setParameters(PreparedStatement ps, List cacheParams)
> > +        throws SQLException {
> > +        List params = ((cacheParams != null && cacheParams.size() > 0)
> > ?
> > +            cacheParams : _params);
> > +
> > +        if (params == null)
> >            return;
> >
> >        Column col;
> > -        for (int i = 0; i < _params.size(); i++) {
> > +        for (int i = 0; i < params.size(); i++) {
> >            col = (_cols == null) ? null : (Column) _cols.get(i);
> > -            _dict.setUnknown(ps, i + 1, _params.get(i), col);
> > +            _dict.setUnknown(ps, i + 1, params.get(i), col);
> >        }
> >    }
> >
> >
> > Modified:
> > openjpa/trunk/openjpa-jdbc/src/main/java/org/apache/openjpa/jdbc/sql/Select.java
> > URL:
> > http://svn.apache.org/viewvc/openjpa/trunk/openjpa-jdbc/src/main/java/org/apache/openjpa/jdbc/sql/Select.java?rev=652913&r1=652912&r2=652913&view=diff
> >
> > ==============================================================================
> > ---
> > openjpa/trunk/openjpa-jdbc/src/main/java/org/apache/openjpa/jdbc/sql/Select.java
> > (original)
> > +++
> > openjpa/trunk/openjpa-jdbc/src/main/java/org/apache/openjpa/jdbc/sql/Select.java
> > Fri May  2 14:09:14 2008
> > @@ -193,6 +193,19 @@
> >    public SQLBuffer getHaving();
> >
> >    /**
> > +     * Return the SQL for this select. This buffer contains
> > +     * the final SQL to be executed/cached.
> > +     */
> > +    public SQLBuffer getSQL();
> > +
> > +    /**
> > +     * Create and set the SQLBuffer object to this select. This buffer
> > contains
> > +     * the final SQL to be executed/cached.
> > +     */
> > +    public void setSQL(JDBCStore store, JDBCFetchConfiguration fetch);
> > +
> > +
> > +    /**
> >     * Apply class conditions from relation joins.  This may affect the
> > return
> >     * values of {@link #getJoins}, {@link #getJoinIterator}, and
> >     * {@link #getWhere}.
> > @@ -515,6 +528,19 @@
> >     */
> >    public void wherePrimaryKey(Object oid, ClassMapping mapping,
> >        JDBCStore store);
> > +
> > +
> > +    /**
> > +     * Add where conditions setting the mapping's primary key to the
> > given
> > +     * oid values. If the parmList is not null, the value of the
> > primary
> > +     * key will be collected and saved into the parmList. If the
> > parmList is
> > +     * null, this method will build the where clause with the value
> > +     * incorporated in the where clause.
> > +     */
> > +    public int wherePrimaryKey(ClassMapping mapping, Column[] toCols,
> > +            Column[] fromCols, Object oid, JDBCStore store, PathJoins
> > pj,
> > +            SQLBuffer buf, List parmList);
> > +
> >
> >    /**
> >     * Add where conditions setting the given foreign key to the given
> >
> > Modified:
> > openjpa/trunk/openjpa-jdbc/src/main/java/org/apache/openjpa/jdbc/sql/SelectExecutor.java
> > URL:
> > http://svn.apache.org/viewvc/openjpa/trunk/openjpa-jdbc/src/main/java/org/apache/openjpa/jdbc/sql/SelectExecutor.java?rev=652913&r1=652912&r2=652913&view=diff
> >
> > ==============================================================================
> > ---
> > openjpa/trunk/openjpa-jdbc/src/main/java/org/apache/openjpa/jdbc/sql/SelectExecutor.java
> > (original)
> > +++
> > openjpa/trunk/openjpa-jdbc/src/main/java/org/apache/openjpa/jdbc/sql/SelectExecutor.java
> > Fri May  2 14:09:14 2008
> > @@ -19,6 +19,7 @@
> > package org.apache.openjpa.jdbc.sql;
> >
> > import java.sql.SQLException;
> > +import java.util.List;
> >
> > import org.apache.openjpa.jdbc.conf.JDBCConfiguration;
> > import org.apache.openjpa.jdbc.kernel.JDBCFetchConfiguration;
> > @@ -133,6 +134,20 @@
> >     * Execute this select in the context of the given store manager.
> >     */
> >    public Result execute(JDBCStore store, JDBCFetchConfiguration fetch,
> > +        List params)
> > +        throws SQLException;
> > +
> > +    /**
> > +     * Execute this select in the context of the given store manager.
> > +     */
> > +    public Result execute(JDBCStore store, JDBCFetchConfiguration
> > fetch,
> > +        int lockLevel, List params)
> > +        throws SQLException;
> > +
> > +    /**
> > +     * Execute this select in the context of the given store manager.
> > +     */
> > +    public Result execute(JDBCStore store, JDBCFetchConfiguration
> > fetch,
> >        int lockLevel)
> >        throws SQLException;
> > }
> >
> > Modified:
> > openjpa/trunk/openjpa-jdbc/src/main/java/org/apache/openjpa/jdbc/sql/SelectImpl.java
> > URL:
> > http://svn.apache.org/viewvc/openjpa/trunk/openjpa-jdbc/src/main/java/org/apache/openjpa/jdbc/sql/SelectImpl.java?rev=652913&r1=652912&r2=652913&view=diff
> >
> > ==============================================================================
> > ---
> > openjpa/trunk/openjpa-jdbc/src/main/java/org/apache/openjpa/jdbc/sql/SelectImpl.java
> > (original)
> > +++
> > openjpa/trunk/openjpa-jdbc/src/main/java/org/apache/openjpa/jdbc/sql/SelectImpl.java
> > Fri May  2 14:09:14 2008
> > @@ -118,6 +118,9 @@
> >    // 'parent.address.street' for the purposes of comparisons
> >    private Map _aliases = null;
> >
> > +    // to cache table alias using Table as the key
> > +    private Map _tableAliases = null;
> > +
> >    // map of indexes to table aliases like 'TABLENAME t0'
> >    private SortedMap _tables = null;
> >
> > @@ -167,7 +170,10 @@
> >    // if the bit is set, the corresponding alias has been removed from
> > parent
> >    // and recorded under subselect.
> >    private BitSet _removedAliasFromParent = new BitSet(16);
> > -
> > +
> > +    //contains final sql statement to be executed/cached
> > +    private SQLBuffer _sql = null;
> > +
> >    /**
> >     * Helper method to return the proper table alias for the given alias
> > index.
> >     */
> > @@ -300,7 +306,7 @@
> >            stmnt = prepareStatement(conn, sql, null,
> >                ResultSet.TYPE_FORWARD_ONLY,
> >                ResultSet.CONCUR_READ_ONLY, false);
> > -            rs = executeQuery(conn, stmnt, sql, false, store);
> > +            rs = executeQuery(conn, stmnt, sql, false, store, null);
> >            return getCount(rs);
> >        } finally {
> >            if (rs != null)
> > @@ -312,20 +318,31 @@
> >        }
> >    }
> >
> > -    public Result execute(JDBCStore store, JDBCFetchConfiguration
> > fetch)
> > -        throws SQLException {
> > +    public Result execute(JDBCStore store, JDBCFetchConfiguration
> > fetch,
> > +        List parms) throws SQLException {
> >        if (fetch == null)
> >            fetch = store.getFetchConfiguration();
> >        return execute(store.getContext(), store, fetch,
> > -            fetch.getReadLockLevel());
> > +            fetch.getReadLockLevel(), parms);
> > +    }
> > +
> > +    public Result execute(JDBCStore store, JDBCFetchConfiguration
> > fetch)
> > +        throws SQLException {
> > +        return execute(store, fetch, null);
> > +     }
> > +
> > +    public Result execute(JDBCStore store, JDBCFetchConfiguration
> > fetch,
> > +        int lockLevel, List parms)
> > +        throws SQLException {
> > +            if (fetch == null)
> > +                fetch = store.getFetchConfiguration();
> > +            return execute(store.getContext(), store, fetch, lockLevel,
> > parms);
> >    }
> >
> >    public Result execute(JDBCStore store, JDBCFetchConfiguration fetch,
> >        int lockLevel)
> >        throws SQLException {
> > -        if (fetch == null)
> > -            fetch = store.getFetchConfiguration();
> > -        return execute(store.getContext(), store, fetch, lockLevel);
> > +        return execute(store, fetch, lockLevel, null);
> >    }
> >
> >    /**
> > @@ -333,16 +350,21 @@
> >     * context is passed in separately for profiling purposes.
> >     */
> >    protected Result execute(StoreContext ctx, JDBCStore store,
> > -        JDBCFetchConfiguration fetch, int lockLevel)
> > +        JDBCFetchConfiguration fetch, int lockLevel, List params)
> >        throws SQLException {
> > -        boolean forUpdate = false;
> > -        if (!isAggregate() && _grouping == null) {
> > -            JDBCLockManager lm = store.getLockManager();
> > -            if (lm != null)
> > -                forUpdate = lm.selectForUpdate(this, lockLevel);
> > -        }
> > -
> > -        SQLBuffer sql = toSelect(forUpdate, fetch);
> > +        boolean forUpdate = isForUpdate(store, lockLevel);
> > +
> > +        // A non-null _sql indicates that this SelectImpl object
> > +        // is obtained from cache. The _sql is constructed
> > +        // under the assumption that isAggregate() is false
> > +        // and _grouping is null. If neither of these holds,
> > +        // we need to re-construct the _sql
> > +        if (_sql != null && (isAggregate() || _grouping != null))
> > +            _sql = null;
> > +
> > +        if (_sql == null)
> > +               _sql = toSelect(forUpdate, fetch);
> > +
> >        boolean isLRS = isLRS();
> >        int rsType = (isLRS && supportsRandomAccess(forUpdate))
> >            ? -1 : ResultSet.TYPE_FORWARD_ONLY;
> > @@ -351,13 +373,15 @@
> >        ResultSet rs = null;
> >        try {
> >            if (isLRS)
> > -                stmnt = prepareStatement(conn, sql, fetch, rsType, -1,
> > true);
> > +                stmnt = prepareStatement(conn, _sql, fetch, rsType, -1,
> > true,
> > +                        params);
> >            else
> > -                stmnt = prepareStatement(conn, sql, null, rsType, -1,
> > false);
> > +                stmnt = prepareStatement(conn, _sql, null, rsType, -1,
> > false,
> > +                        params);
> >
> >            setTimeout(stmnt, forUpdate, fetch);
> >
> > -            rs = executeQuery(conn, stmnt, sql, isLRS, store);
> > +            rs = executeQuery(conn, stmnt, _sql, isLRS, store, params);
> >        } catch (SQLException se) {
> >            // clean up statement
> >            if (stmnt != null)
> > @@ -367,7 +391,17 @@
> >        }
> >
> >        return getEagerResult(conn, stmnt, rs, store, fetch, forUpdate,
> > -            sql.getSQL());
> > +            _sql.getSQL());
> > +    }
> > +
> > +    private boolean isForUpdate(JDBCStore store, int lockLevel) {
> > +       boolean forUpdate = false;
> > +        if (!isAggregate() && _grouping == null) {
> > +            JDBCLockManager lm = store.getLockManager();
> > +            if (lm != null)
> > +                forUpdate = lm.selectForUpdate(this, lockLevel);
> > +        }
> > +        return forUpdate;
> >    }
> >
> >    /**
> > @@ -413,10 +447,22 @@
> >    protected PreparedStatement prepareStatement(Connection conn,
> >        SQLBuffer sql, JDBCFetchConfiguration fetch, int rsType,
> >        int rsConcur, boolean isLRS) throws SQLException {
> > +        // add comments why we pass in null as the last parameter
> > +        return prepareStatement(conn, sql, fetch, rsType, rsConcur,
> > isLRS,
> > +                null);
> > +    }
> > +
> > +    /**
> > +     * This method is to provide override for non-JDBC or JDBC-like
> > +     * implementation of preparing statement.
> > +     */
> > +    protected PreparedStatement prepareStatement(Connection conn,
> > +        SQLBuffer sql, JDBCFetchConfiguration fetch, int rsType,
> > +        int rsConcur, boolean isLRS, List params) throws SQLException {
> >        if (fetch == null)
> > -            return sql.prepareStatement(conn, rsType, rsConcur);
> > +            return sql.prepareStatement(conn, rsType, rsConcur,
> > params);
> >        else
> > -            return sql.prepareStatement(conn, fetch, rsType, -1);
> > +            return sql.prepareStatement(conn, fetch, rsType, -1,
> > params);
> >    }
> >
> >    /**
> > @@ -445,7 +491,8 @@
> >     * implementation of executing query.
> >     */
> >    protected ResultSet executeQuery(Connection conn, PreparedStatement
> > stmnt,
> > -        SQLBuffer sql, boolean isLRS, JDBCStore store) throws
> > SQLException {
> > +        SQLBuffer sql, boolean isLRS, JDBCStore store, List params)
> > +        throws SQLException {
> >        return stmnt.executeQuery();
> >    }
> >
> > @@ -589,6 +636,19 @@
> >        return _having;
> >    }
> >
> > +    public SQLBuffer getSQL() {
> > +        return _sql;
> > +    }
> > +
> > +    public void setSQL(SQLBuffer sql) {
> > +        _sql = sql;
> > +    }
> > +
> > +    public void setSQL(JDBCStore store, JDBCFetchConfiguration fetch) {
> > +        boolean forUpdate = isForUpdate(store,
> > fetch.getReadLockLevel());
> > +        _sql = toSelect(forUpdate, fetch);
> > +    }
> > +
> >    public void addJoinClassConditions() {
> >        if (_joins == null || _joins.joins() == null)
> >            return;
> > @@ -656,13 +716,30 @@
> >     * Return the alias for the given column.
> >     */
> >    private String getColumnAlias(String col, Table table, PathJoins pj)
> > {
> > +        String tableAlias = null;
> > +        if (pj == null || pj.path() == null) {
> > +            if (_tableAliases == null)
> > +                _tableAliases = new HashMap();
> > +            tableAlias = (String) _tableAliases.get(table);
> > +            if (tableAlias == null) {
> > +                tableAlias = getTableAlias(table, pj).toString();
> > +                _tableAliases.put(table, tableAlias);
> > +            }
> > +            return new
> > StringBuilder(tableAlias).append(col).toString();
> > +        }
> > +        return getTableAlias(table, pj).append(col).toString();
> > +    }
> > +
> > +    private StringBuilder getTableAlias(Table table, PathJoins pj) {
> > +        StringBuilder buf = new StringBuilder();
> >        if (_from != null) {
> >            String alias = toAlias(_from.getTableIndex(table, pj, true));
> >            if (_dict.requiresAliasForSubselect)
> > -                return FROM_SELECT_ALIAS + "." + alias + "_" + col;
> > -            return alias + "_" + col;
> > +                return
> > buf.append(FROM_SELECT_ALIAS).append(".").append(alias).
> > +                    append("_");
> > +            return buf.append(alias).append("_");
> >        }
> > -        return toAlias(getTableIndex(table, pj, true)) + "." + col;
> > +        return buf.append(toAlias(getTableIndex(table, pj,
> > true))).append(".");
> >    }
> >
> >    public boolean isAggregate() {
> > @@ -1263,12 +1340,38 @@
> >            return;
> >        }
> >
> > +        SQLBuffer buf = new SQLBuffer(_dict);
> > +
> > +        // only bother to pack pk values into array if app id
> > +        int count = wherePrimaryKey(mapping, toCols, fromCols, oid,
> > store, pj,
> > +               buf, null);
> > +
> > +        if (constCols != null && constCols.length > 0) {
> > +            for (int i = 0; i < constCols.length; i++, count++) {
> > +                if (count > 0)
> > +                    buf.append(" AND ");
> > +                buf.append(getColumnAlias(constCols[i], pj));
> > +
> > +                if (vals[i] == null)
> > +                    buf.append(" IS ");
> > +                else
> > +                    buf.append(" = ");
> > +                buf.appendValue(vals[i], constCols[i]);
> > +            }
> > +        }
> > +
> > +        where(buf, pj);
> > +    }
> > +
> > +    public int wherePrimaryKey(ClassMapping mapping, Column[] toCols,
> > +       Column[] fromCols, Object oid, JDBCStore store, PathJoins pj,
> > +       SQLBuffer buf, List parmList) {
> >        // only bother to pack pk values into array if app id
> > +       boolean collectParmValueOnly = (parmList != null ? true :
> > false);
> >        Object[] pks = null;
> >        if (mapping.getIdentityType() == ClassMapping.ID_APPLICATION)
> >            pks = ApplicationIds.toPKValues(oid, mapping);
> >
> > -        SQLBuffer buf = new SQLBuffer(_dict);
> >        Joinable join;
> >        Object val;
> >        int count = 0;
> > @@ -1281,8 +1384,13 @@
> >                val = pks[mapping.getField(join.getFieldIndex()).
> >                    getPrimaryKeyIndex()];
> >                val = join.getJoinValue(val, toCols[i], store);
> > +                if (parmList != null)
> > +                       parmList.add(val);
> >            }
> > -
> > +
> > +            if (collectParmValueOnly)
> > +               continue;
> > +
> >            if (count > 0)
> >                buf.append(" AND ");
> >            buf.append(getColumnAlias(fromCols[i], pj));
> > @@ -1292,24 +1400,9 @@
> >                buf.append(" = ");
> >            buf.appendValue(val, fromCols[i]);
> >        }
> > -
> > -        if (constCols != null && constCols.length > 0) {
> > -            for (int i = 0; i < constCols.length; i++, count++) {
> > -                if (count > 0)
> > -                    buf.append(" AND ");
> > -                buf.append(getColumnAlias(constCols[i], pj));
> > -
> > -                if (vals[i] == null)
> > -                    buf.append(" IS ");
> > -                else
> > -                    buf.append(" = ");
> > -                buf.appendValue(vals[i], constCols[i]);
> > -            }
> > -        }
> > -
> > -        where(buf, pj);
> > +        return count;
> >    }
> > -
> > +
> >    /**
> >     * Test to see if the given set of columns contains all the
> >     * columns in the given potential subset.
> >
> > Modified:
> > openjpa/trunk/openjpa-jdbc/src/main/resources/org/apache/openjpa/jdbc/kernel/localizer.properties
> > URL:
> > http://svn.apache.org/viewvc/openjpa/trunk/openjpa-jdbc/src/main/resources/org/apache/openjpa/jdbc/kernel/localizer.properties?rev=652913&r1=652912&r2=652913&view=diff
> >
> > ==============================================================================
> > ---
> > openjpa/trunk/openjpa-jdbc/src/main/resources/org/apache/openjpa/jdbc/kernel/localizer.properties
> > (original)
> > +++
> > openjpa/trunk/openjpa-jdbc/src/main/resources/org/apache/openjpa/jdbc/kernel/localizer.properties
> > Fri May  2 14:09:14 2008
> > @@ -113,4 +113,5 @@
> > batch_limit: The batch limit is set to {0}.
> > batch_update_info: ExecuteBatch command returns update count {0} for \
> >        statement {1}.
> > -
> > +cache-hit: SQL Cache hit with key: {0} in {1}
> > +cache-missed: SQL Cache missed with key: {0} in {1}
> >
> > Modified:
> > openjpa/trunk/openjpa-jdbc/src/main/resources/org/apache/openjpa/jdbc/meta/strats/localizer.properties
> > URL:
> > http://svn.apache.org/viewvc/openjpa/trunk/openjpa-jdbc/src/main/resources/org/apache/openjpa/jdbc/meta/strats/localizer.properties?rev=652913&r1=652912&r2=652913&view=diff
> >
> > ==============================================================================
> > ---
> > openjpa/trunk/openjpa-jdbc/src/main/resources/org/apache/openjpa/jdbc/meta/strats/localizer.properties
> > (original)
> > +++
> > openjpa/trunk/openjpa-jdbc/src/main/resources/org/apache/openjpa/jdbc/meta/strats/localizer.properties
> > Fri May  2 14:09:14 2008
> > @@ -134,3 +134,5 @@
> >        its "{1}" primary key field does not use a simple mapping.
> > unmapped-datastore-value: Instances of type "{0}" are not valid query \
> >        parameters because the type is not mapped.
> > +cache-hit: SQL Cache hit with key: {0} in {1}
> > +cache-missed: SQL Cache missed with key: {0} in {1}
> >
> > Modified:
> > openjpa/trunk/openjpa-kernel/src/main/java/org/apache/openjpa/kernel/FetchConfigurationImpl.java
> > URL:
> > http://svn.apache.org/viewvc/openjpa/trunk/openjpa-kernel/src/main/java/org/apache/openjpa/kernel/FetchConfigurationImpl.java?rev=652913&r1=652912&r2=652913&view=diff
> >
> > ============================================================================
>
> ...
>
> [Message clipped]