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 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 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 > > 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 > > 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]