From eb777be3acbda2ac8823278e8c8cd275fc3fa30d Mon Sep 17 00:00:00 2001 From: Patrick Linskey Date: Tue, 7 Nov 2006 19:33:43 +0000 Subject: [PATCH] Moved Kodo query compilation cache into OpenJPA. git-svn-id: https://svn.apache.org/repos/asf/incubator/openjpa/trunk@472218 13f79535-47bb-0310-9956-ffa450edef68 --- .../openjpa/conf/OpenJPAConfiguration.java | 22 ++ .../conf/OpenJPAConfigurationImpl.java | 281 +++++++++--------- .../conf/QueryCompilationCacheValue.java | 60 ++++ .../org/apache/openjpa/kernel/QueryImpl.java | 85 +++++- .../apache/openjpa/meta/ClassMetaData.java | 1 - .../apache/openjpa/conf/localizer.properties | 11 + .../src/doc/manual/ref_guide_caching.xml | 78 +++++ .../src/doc/manual/ref_guide_conf.xml | 28 ++ .../src/doc/manual/ref_guide_optimization.xml | 16 + 9 files changed, 442 insertions(+), 140 deletions(-) create mode 100644 openjpa-kernel/src/main/java/org/apache/openjpa/conf/QueryCompilationCacheValue.java diff --git a/openjpa-kernel/src/main/java/org/apache/openjpa/conf/OpenJPAConfiguration.java b/openjpa-kernel/src/main/java/org/apache/openjpa/conf/OpenJPAConfiguration.java index 1c378b732..4091775be 100644 --- a/openjpa-kernel/src/main/java/org/apache/openjpa/conf/OpenJPAConfiguration.java +++ b/openjpa-kernel/src/main/java/org/apache/openjpa/conf/OpenJPAConfiguration.java @@ -16,6 +16,7 @@ package org.apache.openjpa.conf; import java.util.Collection; +import java.util.Map; import org.apache.openjpa.datacache.DataCache; import org.apache.openjpa.datacache.DataCacheManager; @@ -1355,6 +1356,27 @@ public interface OpenJPAConfiguration * Backwards compatibility options. */ public Compatibility getCompatibilityInstance (); + + /** + * Configuration settings for the query compilation cache to use. + * @see QueryCompilationCacheValue + * @since 0.9.6 + */ + public String getQueryCompilationCache(); + + /** + * Configuration settings for the query compilation cache to use. + * @see QueryCompilationCacheValue + * @since 0.9.6 + */ + public void setQueryCompilationCache(String conf); + + /** + * Configuration settings for the query compilation cache to use. + * @see QueryCompilationCacheValue + * @since 0.9.6 + */ + public Map getQueryCompilationCacheInstance(); /** * Return the {@link StoreFacadeTypeRegistry} instance associated with this diff --git a/openjpa-kernel/src/main/java/org/apache/openjpa/conf/OpenJPAConfigurationImpl.java b/openjpa-kernel/src/main/java/org/apache/openjpa/conf/OpenJPAConfigurationImpl.java index 86f78f64d..f28a25ff3 100644 --- a/openjpa-kernel/src/main/java/org/apache/openjpa/conf/OpenJPAConfigurationImpl.java +++ b/openjpa-kernel/src/main/java/org/apache/openjpa/conf/OpenJPAConfigurationImpl.java @@ -17,6 +17,8 @@ package org.apache.openjpa.conf; import java.util.Collection; import java.util.HashSet; +import java.util.Map; + import org.apache.commons.lang.StringUtils; import org.apache.openjpa.datacache.ConcurrentDataCache; import org.apache.openjpa.datacache.ConcurrentQueryCache; @@ -59,8 +61,8 @@ public class OpenJPAConfigurationImpl extends ConfigurationImpl implements OpenJPAConfiguration { - private static final Localizer _loc = Localizer.forPackage - (OpenJPAConfigurationImpl.class); + private static final Localizer _loc = + Localizer.forPackage(OpenJPAConfigurationImpl.class); // cached state; some of this is created in getter methods, so make // protected in case subclasses want to access without creating @@ -124,6 +126,7 @@ public class OpenJPAConfigurationImpl public ObjectValue savepointManagerPlugin; public ObjectValue orphanedKeyPlugin; public ObjectValue compatibilityPlugin; + public QueryCompilationCacheValue queryCompilationCachePlugin; // custom values public BrokerFactoryValue brokerFactoryPlugin; @@ -162,11 +165,11 @@ public class OpenJPAConfigurationImpl String[] aliases; classResolverPlugin = addPlugin("ClassResolver", true); - aliases = new String[]{ - "default", "org.apache.openjpa.util.ClassResolverImpl", - // deprecated alias - "spec", "org.apache.openjpa.util.ClassResolverImpl", - }; + aliases = + new String[] { "default", + "org.apache.openjpa.util.ClassResolverImpl", + // deprecated alias + "spec", "org.apache.openjpa.util.ClassResolverImpl", }; classResolverPlugin.setAliases(aliases); classResolverPlugin.setDefault(aliases[0]); classResolverPlugin.setString(aliases[0]); @@ -176,26 +179,24 @@ public class OpenJPAConfigurationImpl addValue(brokerFactoryPlugin); brokerPlugin = addPlugin("BrokerImpl", false); - aliases = new String[]{ "default", BrokerImpl.class.getName() }; + aliases = new String[] { "default", BrokerImpl.class.getName() }; brokerPlugin.setAliases(aliases); brokerPlugin.setDefault(aliases[0]); brokerPlugin.setString(aliases[0]); dataCacheManagerPlugin = addPlugin("DataCacheManager", true); - aliases = new String[]{ - "default", DataCacheManagerImpl.class.getName(), - }; + aliases = + new String[] { "default", DataCacheManagerImpl.class.getName(), }; dataCacheManagerPlugin.setAliases(aliases); dataCacheManagerPlugin.setDefault(aliases[0]); dataCacheManagerPlugin.setString(aliases[0]); dataCacheManagerPlugin.setInstantiatingGetter("getDataCacheManager"); dataCachePlugin = addPlugin("DataCache", false); - aliases = new String[]{ - "false", null, - "true", ConcurrentDataCache.class.getName(), - "concurrent", ConcurrentDataCache.class.getName(), - }; + aliases = + new String[] { "false", null, "true", + ConcurrentDataCache.class.getName(), "concurrent", + ConcurrentDataCache.class.getName(), }; dataCachePlugin.setAliases(aliases); dataCachePlugin.setDefault(aliases[0]); dataCachePlugin.setString(aliases[0]); @@ -205,11 +206,10 @@ public class OpenJPAConfigurationImpl dataCacheTimeout.set(-1); queryCachePlugin = addPlugin("QueryCache", true); - aliases = new String[]{ - "true", ConcurrentQueryCache.class.getName(), - "concurrent", ConcurrentQueryCache.class.getName(), - "false", null, - }; + aliases = + new String[] { "true", ConcurrentQueryCache.class.getName(), + "concurrent", ConcurrentQueryCache.class.getName(), "false", + null, }; queryCachePlugin.setAliases(aliases); queryCachePlugin.setDefault(aliases[0]); queryCachePlugin.setString(aliases[0]); @@ -219,71 +219,67 @@ public class OpenJPAConfigurationImpl dynamicDataStructs.set(false); lockManagerPlugin = addPlugin("LockManager", false); - aliases = new String[]{ - "none", "org.apache.openjpa.kernel.NoneLockManager", - "version", "org.apache.openjpa.kernel.VersionLockManager", - }; + aliases = + new String[] { "none", "org.apache.openjpa.kernel.NoneLockManager", + "version", "org.apache.openjpa.kernel.VersionLockManager", }; lockManagerPlugin.setAliases(aliases); lockManagerPlugin.setDefault(aliases[0]); lockManagerPlugin.setString(aliases[0]); inverseManagerPlugin = addPlugin("InverseManager", false); - aliases = new String[]{ - "false", null, - "true", "org.apache.openjpa.kernel.InverseManager", - }; + aliases = + new String[] { "false", null, "true", + "org.apache.openjpa.kernel.InverseManager", }; inverseManagerPlugin.setAliases(aliases); inverseManagerPlugin.setDefault(aliases[0]); inverseManagerPlugin.setString(aliases[0]); savepointManagerPlugin = addPlugin("SavepointManager", true); - aliases = new String[]{ - "in-mem", "org.apache.openjpa.kernel.InMemorySavepointManager", - }; + aliases = + new String[] { "in-mem", + "org.apache.openjpa.kernel.InMemorySavepointManager", }; savepointManagerPlugin.setAliases(aliases); savepointManagerPlugin.setDefault(aliases[0]); savepointManagerPlugin.setString(aliases[0]); - savepointManagerPlugin.setInstantiatingGetter - ("getSavepointManagerInstance"); + savepointManagerPlugin + .setInstantiatingGetter("getSavepointManagerInstance"); orphanedKeyPlugin = addPlugin("OrphanedKeyAction", true); - aliases = new String[]{ - "log", "org.apache.openjpa.event.LogOrphanedKeyAction", - "exception", "org.apache.openjpa.event.ExceptionOrphanedKeyAction", - "none", "org.apache.openjpa.event.NoneOrphanedKeyAction", - }; + aliases = + new String[] { "log", + "org.apache.openjpa.event.LogOrphanedKeyAction", "exception", + "org.apache.openjpa.event.ExceptionOrphanedKeyAction", "none", + "org.apache.openjpa.event.NoneOrphanedKeyAction", }; orphanedKeyPlugin.setAliases(aliases); orphanedKeyPlugin.setDefault(aliases[0]); orphanedKeyPlugin.setString(aliases[0]); - orphanedKeyPlugin.setInstantiatingGetter - ("getOrphanedKeyActionInstance"); + orphanedKeyPlugin + .setInstantiatingGetter("getOrphanedKeyActionInstance"); remoteProviderPlugin = new RemoteCommitProviderValue(); addValue(remoteProviderPlugin); transactionMode = addBoolean("TransactionMode"); - aliases = new String[]{ - "local", "false", - "managed", "true", - }; + aliases = new String[] { "local", "false", "managed", "true", }; transactionMode.setAliases(aliases); transactionMode.setDefault(aliases[0]); managedRuntimePlugin = addPlugin("ManagedRuntime", true); - aliases = new String[]{ - "auto", "org.apache.openjpa.ee.AutomaticManagedRuntime", - "jndi", "org.apache.openjpa.ee.JNDIManagedRuntime", - "invocation", "org.apache.openjpa.ee.InvocationManagedRuntime", - }; + aliases = + new String[] { "auto", + "org.apache.openjpa.ee.AutomaticManagedRuntime", "jndi", + "org.apache.openjpa.ee.JNDIManagedRuntime", "invocation", + "org.apache.openjpa.ee.InvocationManagedRuntime", }; managedRuntimePlugin.setAliases(aliases); managedRuntimePlugin.setDefault(aliases[0]); managedRuntimePlugin.setString(aliases[0]); - managedRuntimePlugin.setInstantiatingGetter - ("getManagedRuntimeInstance"); + managedRuntimePlugin + .setInstantiatingGetter("getManagedRuntimeInstance"); proxyManagerPlugin = addPlugin("ProxyManager", true); - aliases = new String[]{ "default", - "org.apache.openjpa.util.ProxyManagerImpl" }; + aliases = + new String[] { "default", + "org.apache.openjpa.util.ProxyManagerImpl" }; proxyManagerPlugin.setAliases(aliases); proxyManagerPlugin.setDefault(aliases[0]); proxyManagerPlugin.setString(aliases[0]); @@ -293,8 +289,9 @@ public class OpenJPAConfigurationImpl metaFactoryPlugin = addPlugin("MetaDataFactory", false); metaRepositoryPlugin = addPlugin("MetaDataRepository", false); - aliases = new String[]{ "default", - "org.apache.openjpa.meta.MetaDataRepository" }; + aliases = + new String[] { "default", + "org.apache.openjpa.meta.MetaDataRepository" }; metaRepositoryPlugin.setAliases(aliases); metaRepositoryPlugin.setDefault(aliases[0]); metaRepositoryPlugin.setString(aliases[0]); @@ -317,15 +314,12 @@ public class OpenJPAConfigurationImpl connection2URL = addString("Connection2URL"); connection2DriverName = addString("Connection2DriverName"); connection2Properties = addString("Connection2Properties"); - connectionFactory2Properties = addString( - "ConnectionFactory2Properties"); + connectionFactory2Properties = + addString("ConnectionFactory2Properties"); connectionFactory2Name = addString("ConnectionFactory2Name"); connectionFactoryMode = addBoolean("ConnectionFactoryMode"); - aliases = new String[]{ - "local", "false", - "managed", "true", - }; + aliases = new String[] { "local", "false", "managed", "true", }; connectionFactoryMode.setAliases(aliases); connectionFactoryMode.setDefault(aliases[0]); @@ -334,10 +328,10 @@ public class OpenJPAConfigurationImpl optimistic.set(true); autoClear = addInt("AutoClear"); - aliases = new String[]{ - "datastore", String.valueOf(AutoClear.CLEAR_DATASTORE), - "all", String.valueOf(AutoClear.CLEAR_ALL), - }; + aliases = + new String[] { "datastore", + String.valueOf(AutoClear.CLEAR_DATASTORE), "all", + String.valueOf(AutoClear.CLEAR_ALL), }; autoClear.setAliases(aliases); autoClear.setDefault(aliases[0]); autoClear.set(AutoClear.CLEAR_DATASTORE); @@ -348,14 +342,13 @@ public class OpenJPAConfigurationImpl retainState.set(true); restoreState = addInt("RestoreState"); - aliases = new String[]{ - "none", String.valueOf(RestoreState.RESTORE_NONE), - "false", String.valueOf(RestoreState.RESTORE_NONE), - "immutable", String.valueOf(RestoreState.RESTORE_IMMUTABLE), - // "true" for compat with jdo RestoreValues - "true", String.valueOf(RestoreState.RESTORE_IMMUTABLE), - "all", String.valueOf(RestoreState.RESTORE_ALL), - }; + aliases = + new String[] { "none", String.valueOf(RestoreState.RESTORE_NONE), + "false", String.valueOf(RestoreState.RESTORE_NONE), + "immutable", String.valueOf(RestoreState.RESTORE_IMMUTABLE), + // "true" for compat with jdo RestoreValues + "true", String.valueOf(RestoreState.RESTORE_IMMUTABLE), "all", + String.valueOf(RestoreState.RESTORE_ALL), }; restoreState.setAliases(aliases); restoreState.setDefault(aliases[0]); restoreState.set(RestoreState.RESTORE_IMMUTABLE); @@ -365,11 +358,10 @@ public class OpenJPAConfigurationImpl addValue(autoDetach); detachStatePlugin = addPlugin("DetachState", true); - aliases = new String[]{ - "loaded", DetachOptions.Loaded.class.getName(), - "fgs", DetachOptions.FetchGroups.class.getName(), - "all", DetachOptions.All.class.getName(), - }; + aliases = + new String[] { "loaded", DetachOptions.Loaded.class.getName(), + "fgs", DetachOptions.FetchGroups.class.getName(), "all", + DetachOptions.All.class.getName(), }; detachStatePlugin.setAliases(aliases); detachStatePlugin.setDefault(aliases[0]); detachStatePlugin.setString(aliases[0]); @@ -394,15 +386,14 @@ public class OpenJPAConfigurationImpl fetchGroups = addStringList("FetchGroups"); fetchGroups.setDefault("default"); - fetchGroups.set(new String[]{ "default" }); + fetchGroups.set(new String[] { "default" }); flushBeforeQueries = addInt("FlushBeforeQueries"); - aliases = new String[]{ - "true", String.valueOf(QueryFlushModes.FLUSH_TRUE), - "false", String.valueOf(QueryFlushModes.FLUSH_FALSE), - "with-connection", String.valueOf - (QueryFlushModes.FLUSH_WITH_CONNECTION), - }; + aliases = + new String[] { "true", String.valueOf(QueryFlushModes.FLUSH_TRUE), + "false", String.valueOf(QueryFlushModes.FLUSH_FALSE), + "with-connection", + String.valueOf(QueryFlushModes.FLUSH_WITH_CONNECTION), }; flushBeforeQueries.setAliases(aliases); flushBeforeQueries.setDefault(aliases[0]); flushBeforeQueries.set(QueryFlushModes.FLUSH_TRUE); @@ -413,22 +404,20 @@ public class OpenJPAConfigurationImpl lockTimeout.set(-1); readLockLevel = addInt("ReadLockLevel"); - aliases = new String[]{ - "read", String.valueOf(LockLevels.LOCK_READ), - "write", String.valueOf(LockLevels.LOCK_WRITE), - "none", String.valueOf(LockLevels.LOCK_NONE), - }; + aliases = + new String[] { "read", String.valueOf(LockLevels.LOCK_READ), + "write", String.valueOf(LockLevels.LOCK_WRITE), "none", + String.valueOf(LockLevels.LOCK_NONE), }; readLockLevel.setAliases(aliases); readLockLevel.setDefault(aliases[0]); readLockLevel.set(LockLevels.LOCK_READ); readLockLevel.setAliasListComprehensive(true); writeLockLevel = addInt("WriteLockLevel"); - aliases = new String[]{ - "read", String.valueOf(LockLevels.LOCK_READ), - "write", String.valueOf(LockLevels.LOCK_WRITE), - "none", String.valueOf(LockLevels.LOCK_NONE), - }; + aliases = + new String[] { "read", String.valueOf(LockLevels.LOCK_READ), + "write", String.valueOf(LockLevels.LOCK_WRITE), "none", + String.valueOf(LockLevels.LOCK_NONE), }; writeLockLevel.setAliases(aliases); writeLockLevel.setDefault(aliases[1]); writeLockLevel.set(LockLevels.LOCK_WRITE); @@ -439,38 +428,40 @@ public class OpenJPAConfigurationImpl addValue(seqPlugin); connectionRetainMode = addInt("ConnectionRetainMode"); - aliases = new String[]{ - "on-demand", - String.valueOf(ConnectionRetainModes.CONN_RETAIN_DEMAND), - "transaction", - String.valueOf(ConnectionRetainModes.CONN_RETAIN_TRANS), - "always", - String.valueOf(ConnectionRetainModes.CONN_RETAIN_ALWAYS), - // deprecated - "persistence-manager", - String.valueOf(ConnectionRetainModes.CONN_RETAIN_ALWAYS), - }; + aliases = + new String[] { "on-demand", + String.valueOf(ConnectionRetainModes.CONN_RETAIN_DEMAND), + "transaction", + String.valueOf(ConnectionRetainModes.CONN_RETAIN_TRANS), + "always", + String.valueOf(ConnectionRetainModes.CONN_RETAIN_ALWAYS), + // deprecated + "persistence-manager", + String.valueOf(ConnectionRetainModes.CONN_RETAIN_ALWAYS), }; connectionRetainMode.setAliases(aliases); connectionRetainMode.setDefault(aliases[0]); connectionRetainMode.setAliasListComprehensive(true); connectionRetainMode.set(ConnectionRetainModes.CONN_RETAIN_DEMAND); filterListenerPlugins = addPluginList("FilterListeners"); - filterListenerPlugins.setInstantiatingGetter - ("getFilterListenerInstances"); + filterListenerPlugins + .setInstantiatingGetter("getFilterListenerInstances"); aggregateListenerPlugins = addPluginList("AggregateListeners"); - aggregateListenerPlugins.setInstantiatingGetter - ("getAggregateListenerInstances"); + aggregateListenerPlugins + .setInstantiatingGetter("getAggregateListenerInstances"); retryClassRegistration = addBoolean("RetryClassRegistration"); compatibilityPlugin = addPlugin("Compatibility", true); - aliases = new String[]{ "default", Compatibility.class.getName() }; + aliases = new String[] { "default", Compatibility.class.getName() }; compatibilityPlugin.setAliases(aliases); compatibilityPlugin.setDefault(aliases[0]); compatibilityPlugin.setString(aliases[0]); compatibilityPlugin.setInstantiatingGetter("getCompatibilityInstance"); + + queryCompilationCachePlugin = new QueryCompilationCacheValue(this); + addValue(queryCompilationCachePlugin); // initialize supported options that some runtimes may not support supportedOptions.add(OPTION_NONTRANS_READ); @@ -510,8 +501,8 @@ public class OpenJPAConfigurationImpl if (this.spec != null) { if (!this.spec.equals(spec) && getConfigurationLog().isWarnEnabled()) - getConfigurationLog().warn(_loc.get("diff-specs", this.spec, - spec)); + getConfigurationLog().warn( + _loc.get("diff-specs", this.spec, spec)); return false; } this.spec = spec; @@ -558,8 +549,8 @@ public class OpenJPAConfigurationImpl } public BrokerImpl newBrokerInstance(String user, String pass) { - BrokerImpl broker = (BrokerImpl) brokerPlugin.instantiate - (BrokerImpl.class, this); + BrokerImpl broker = + (BrokerImpl) brokerPlugin.instantiate(BrokerImpl.class, this); if (broker != null) broker.setAuthentication(user, pass); return broker; @@ -584,8 +575,9 @@ public class OpenJPAConfigurationImpl public DataCacheManager getDataCacheManagerInstance() { DataCacheManager dcm = (DataCacheManager) dataCacheManagerPlugin.get(); if (dcm == null) { - dcm = (DataCacheManager) dataCacheManagerPlugin.instantiate - (DataCacheManager.class, this); + dcm = + (DataCacheManager) dataCacheManagerPlugin.instantiate( + DataCacheManager.class, this); dcm.initialize(this, dataCachePlugin, queryCachePlugin); } return dcm; @@ -662,8 +654,8 @@ public class OpenJPAConfigurationImpl } public InverseManager newInverseManagerInstance() { - return (InverseManager) inverseManagerPlugin.instantiate - (InverseManager.class, this); + return (InverseManager) inverseManagerPlugin.instantiate( + InverseManager.class, this); } public void setSavepointManager(String savepointManager) { @@ -714,8 +706,8 @@ public class OpenJPAConfigurationImpl return remoteProviderPlugin.instantiateProvider(this); } - public void setRemoteCommitEventManager - (RemoteCommitEventManager remoteEventManager) { + public void setRemoteCommitEventManager( + RemoteCommitEventManager remoteEventManager) { assertNotReadOnly(); this.remoteEventManager = remoteEventManager; remoteProviderPlugin.configureEventManager(remoteEventManager); @@ -806,8 +798,8 @@ public class OpenJPAConfigurationImpl } public MetaDataFactory newMetaDataFactoryInstance() { - return (MetaDataFactory) metaFactoryPlugin.instantiate - (MetaDataFactory.class, this); + return (MetaDataFactory) metaFactoryPlugin.instantiate( + MetaDataFactory.class, this); } public void setMetaDataRepository(String meta) { @@ -831,8 +823,8 @@ public class OpenJPAConfigurationImpl } public MetaDataRepository newMetaDataRepositoryInstance() { - return (MetaDataRepository) metaRepositoryPlugin.instantiate - (MetaDataRepository.class, this); + return (MetaDataRepository) metaRepositoryPlugin.instantiate( + MetaDataRepository.class, this); } public void setConnectionUserName(String connectionUserName) { @@ -880,8 +872,8 @@ public class OpenJPAConfigurationImpl return connectionProperties.getString(); } - public void setConnectionFactoryProperties - (String connectionFactoryProperties) { + public void setConnectionFactoryProperties( + String connectionFactoryProperties) { assertNotReadOnly(); this.connectionFactoryProperties.setString(connectionFactoryProperties); } @@ -924,8 +916,8 @@ public class OpenJPAConfigurationImpl public Object getConnectionFactory() { if (connectionFactory.get() == null) - connectionFactory.set(lookupConnectionFactory - (getConnectionFactoryName()), true); + connectionFactory.set( + lookupConnectionFactory(getConnectionFactoryName()), true); return connectionFactory.get(); } @@ -984,11 +976,11 @@ public class OpenJPAConfigurationImpl return connection2Properties.getString(); } - public void setConnectionFactory2Properties - (String connectionFactory2Properties) { + public void setConnectionFactory2Properties( + String connectionFactory2Properties) { assertNotReadOnly(); - this.connectionFactory2Properties.setString - (connectionFactory2Properties); + this.connectionFactory2Properties + .setString(connectionFactory2Properties); } public String getConnectionFactory2Properties() { @@ -1011,8 +1003,8 @@ public class OpenJPAConfigurationImpl public Object getConnectionFactory2() { if (connectionFactory2.get() == null) - connectionFactory2.set(lookupConnectionFactory - (getConnectionFactory2Name()), false); + connectionFactory2.set( + lookupConnectionFactory(getConnectionFactory2Name()), false); return connectionFactory2.get(); } @@ -1392,6 +1384,21 @@ public class OpenJPAConfigurationImpl return (Compatibility) compatibilityPlugin.get(); } + public String getQueryCompilationCache() { + return queryCompilationCachePlugin.getString(); + } + + public void setQueryCompilationCache(String conf) { + queryCompilationCachePlugin.setString(conf); + } + + public Map getQueryCompilationCacheInstance() { + if (queryCompilationCachePlugin.get() == null) + queryCompilationCachePlugin.instantiate( + QueryCompilationCacheValue.class, this); + return (Map) queryCompilationCachePlugin.get(); + } + public StoreFacadeTypeRegistry getStoreFacadeTypeRegistry() { return _storeFacadeRegistry; } @@ -1410,5 +1417,5 @@ public class OpenJPAConfigurationImpl public Log getConfigurationLog() { return getLog(LOG_RUNTIME); - } + } } diff --git a/openjpa-kernel/src/main/java/org/apache/openjpa/conf/QueryCompilationCacheValue.java b/openjpa-kernel/src/main/java/org/apache/openjpa/conf/QueryCompilationCacheValue.java new file mode 100644 index 000000000..920a61d0e --- /dev/null +++ b/openjpa-kernel/src/main/java/org/apache/openjpa/conf/QueryCompilationCacheValue.java @@ -0,0 +1,60 @@ +package org.apache.openjpa.conf; + +import java.util.*; + +import org.apache.openjpa.lib.conf.*; +import org.apache.openjpa.lib.util.concurrent.*; +import org.apache.openjpa.util.*; + +/** + *

A cache of compiled queries.

+ * + * @author Abe White + * @since 0.9.6 (also existed in prior versions of Kodo) + * @nojavadoc + */ +public class QueryCompilationCacheValue + extends PluginValue { + + /** + * Query compilation cache configuration property key. + */ + private static final String KEY = "QueryCompilationCache"; + + public static final String[] ALIASES = { + "true", CacheMap.class.getName(), + "all", ConcurrentHashMap.class.getName(), + "false", null, + }; + + private final OpenJPAConfiguration _conf; + + public QueryCompilationCacheValue(OpenJPAConfiguration conf) { + super(KEY, true); + setAliases(ALIASES); + setDefault(ALIASES[0]); + setClassName(ALIASES[1]); + setInstantiatingGetter("this.instantiate"); + setScope(getClass()); + _conf = conf; + } + + /** + * Instantiate internal map. + */ + public void instantiate() { + if (get() == null) + instantiate(Map.class, _conf, true); + } + + public Object newInstance(String clsName, Class type, + Configuration conf, boolean fatal) { + // make sure map handles concurrency + Map map = (Map) super.newInstance(clsName, type, conf, fatal); + if (map != null && !(map instanceof Hashtable) + && !(map instanceof CacheMap) + && !(map instanceof ConcurrentMap)) + map = Collections.synchronizedMap(map); + return map; + } +} diff --git a/openjpa-kernel/src/main/java/org/apache/openjpa/kernel/QueryImpl.java b/openjpa-kernel/src/main/java/org/apache/openjpa/kernel/QueryImpl.java index 644976fb2..8363f1e97 100644 --- a/openjpa-kernel/src/main/java/org/apache/openjpa/kernel/QueryImpl.java +++ b/openjpa-kernel/src/main/java/org/apache/openjpa/kernel/QueryImpl.java @@ -15,6 +15,7 @@ */ package org.apache.openjpa.kernel; +import java.io.Serializable; import java.util.ArrayList; import java.util.Arrays; import java.util.Collection; @@ -26,6 +27,7 @@ import java.util.ListIterator; import java.util.Map; import org.apache.commons.collections.map.LinkedMap; +import org.apache.commons.lang.ObjectUtils; import org.apache.commons.lang.StringUtils; import org.apache.openjpa.conf.OpenJPAConfiguration; import org.apache.openjpa.enhance.PersistenceCapable; @@ -574,7 +576,7 @@ public class QueryImpl _readOnly = false; _compiling = true; try { - _compiled = newCompilation(); + _compiled = compilationFromCache(); return _compiled; } catch (OpenJPAException ke) { throw ke; @@ -589,7 +591,38 @@ public class QueryImpl /** * Create and initialize a query compilation based on current data. */ - protected Compilation newCompilation() { + protected Compilation compilationFromCache() { + Map compCache = + _broker.getConfiguration().getQueryCompilationCacheInstance(); + if (compCache == null) { + return newCompilation(); + } else { + CompilationKey key = new CompilationKey(); + key.queryType = _storeQuery.getClass(); + key.candidateType = getCandidateType(); + key.subclasses = hasSubclasses(); + key.query = getQueryString(); + key.language = getLanguage(); + key.storeKey = _storeQuery.newCompilationKey(); + Compilation comp = (Compilation) compCache.get(key); + + // parse declarations if needed + boolean cache = false; + if (comp == null) { + comp = newCompilation(); + // only cache those queries that can be compiled + cache = comp.storeData != null; + } else + _storeQuery.populateFromCompilation(comp.storeData); + + // cache parsed state if needed + if (cache) + compCache.put(key, comp); + return comp; + } + } + + private Compilation newCompilation() { Compilation comp = new Compilation(); comp.storeData = _storeQuery.newCompilation(); _storeQuery.populateFromCompilation(comp.storeData); @@ -2044,4 +2077,52 @@ public class QueryImpl return _res; } } + + /** + * Struct to hold the unparsed properties associated with a query. + */ + private static class CompilationKey + implements Serializable { + + public Class queryType = null; + public Class candidateType = null; + public boolean subclasses = true; + public String query = null; + public String language = null; + public Object storeKey = null; + + public int hashCode() { + int rs = 17; + rs = 37 * rs + ((queryType == null) ? 0 : queryType.hashCode()); + rs = 37 * rs + ((query == null) ? 0 : query.hashCode()); + rs = 37 * rs + ((language == null) ? 0 : language.hashCode()); + rs = 37 * rs + ((storeKey == null) ? 0 : storeKey.hashCode()); + return rs; + } + + public boolean equals(Object other) { + if (other == this) + return true; + if (other == null || other.getClass() != getClass()) + return false; + + CompilationKey key = (CompilationKey) other; + if (key.queryType != queryType + || !StringUtils.equals(key.query, query) + || !StringUtils.equals(key.language, language)) + return false; + + if (!ObjectUtils.equals(key.storeKey, storeKey)) + return false; + + // allow either candidate type to be null because it might be + // encoded in the query string, but if both are set then they + // must be equal + if (candidateType != null && key.candidateType != null) + return candidateType == key.candidateType + && subclasses == key.subclasses; + + return true; + } + } } diff --git a/openjpa-kernel/src/main/java/org/apache/openjpa/meta/ClassMetaData.java b/openjpa-kernel/src/main/java/org/apache/openjpa/meta/ClassMetaData.java index 73dacb004..6d63551b3 100644 --- a/openjpa-kernel/src/main/java/org/apache/openjpa/meta/ClassMetaData.java +++ b/openjpa-kernel/src/main/java/org/apache/openjpa/meta/ClassMetaData.java @@ -1900,7 +1900,6 @@ public class ClassMetaData String cap; int type; Class c; - ClassMetaData idmeta; int access = meta.getAccessType(); for (int i = 0; i < fmds.length; i++) { switch (fmds[i].getDeclaredTypeCode()) { diff --git a/openjpa-kernel/src/main/resources/org/apache/openjpa/conf/localizer.properties b/openjpa-kernel/src/main/resources/org/apache/openjpa/conf/localizer.properties index 06610582f..5de315f10 100644 --- a/openjpa-kernel/src/main/resources/org/apache/openjpa/conf/localizer.properties +++ b/openjpa-kernel/src/main/resources/org/apache/openjpa/conf/localizer.properties @@ -532,6 +532,17 @@ Compatibility-displayorder: 50 Compatibility-expert: true Compatibility-interface: org.apache.openjpa.conf.Compatibility +QueryCompilationCache-name: Query compilation cache +QueryCompilationCache-desc: Plugin used to cache query compilation data. \ + Must implement java.util.Map. Does not need to be thread-safe -- it will \ + be wrapped via the Collections.synchronizedMap() method if it does not \ + extend org.apache.openjpa.util.CacheMap. +QueryCompilationCache-type: General +QueryCompilationCache-cat: Cache.Queries +QueryCompilationCache-displayorder: 50 +QueryCompilationCache-expert: true +QueryCompilationCache-interface: java.util.Map + no-named-cf: use a DataSource bound to JNDI diff-specs: Attempt to configure for multiple specifications. Was configured \ for "{0}". Attempt to now configure for "{1}". This attempt will be \ diff --git a/openjpa-project/src/doc/manual/ref_guide_caching.xml b/openjpa-project/src/doc/manual/ref_guide_caching.xml index d5695099c..d21bddd75 100644 --- a/openjpa-project/src/doc/manual/ref_guide_caching.xml +++ b/openjpa-project/src/doc/manual/ref_guide_caching.xml @@ -788,4 +788,82 @@ Iterator cachedIterator = extentQuery.getResultList().iterator(); +
+ Query Compilation Cache + + caching + query compilation cache + + + The query compilation cache is a Map used to + cache parsed query strings. As a result, most queries are + only parsed once in OpenJPA, and cached thereafter. You can control the + compilation cache through the + + openjpa.QueryCompilationCache configuration property. + This property accepts a plugin string (see + ) describing the + Map used to associate query strings and their + parsed form. This property accepts the following aliases: + + + Pre-defined aliases + + + + + + + Alias + Value + Notes + + + + + + true + + + org.apache.openjpa.util.CacheMap + + + The default option. Uses a + + CacheMap to store + compilation data. CacheMap uses + a least-recently-used strategy for a fixed number + of cache entries, and an optional soft reference + map for entries that are moved out of the LRU + space. So, for applications that have a + monotonically increasing number of distinct queries, + this option can be used to ensure that a fixed + amount of memory is used by the cache. + + + + all + + org.apache.openjpa.lib.util.ConcurrentHashMap + + + This is the fastest option, but compilation data is + never dropped from the cache, so if you use a large + number of dynamic queries, this option may result in + ever-increasing memory usage. Note that if your + queries only differ in the values of the parameters, + this should not be an issue. + + + + false + none + + Disables the compilation cache. + + + + +
+
diff --git a/openjpa-project/src/doc/manual/ref_guide_conf.xml b/openjpa-project/src/doc/manual/ref_guide_conf.xml index 6d81be27f..e32880861 100644 --- a/openjpa-project/src/doc/manual/ref_guide_conf.xml +++ b/openjpa-project/src/doc/manual/ref_guide_conf.xml @@ -2454,6 +2454,34 @@ implementation to use for caching of queries loaded from the data store. See for details. +
+ openjpa.QueryCompilationCache + + QueryCompilationCache + + + caching + QueryCompilationCache + + + Property name: + openjpa.QueryCompilationCache + + + Resource adaptor config-property: + QueryCompilationCache + + + Default: true. + + + Description: A plugin + string (see ) + describing the java.util.Map to use for + caching of data used during query compilation. + See for details. + +
openjpa.ReadLockLevel diff --git a/openjpa-project/src/doc/manual/ref_guide_optimization.xml b/openjpa-project/src/doc/manual/ref_guide_optimization.xml index 4d0dc7bea..d15d07754 100644 --- a/openjpa-project/src/doc/manual/ref_guide_optimization.xml +++ b/openjpa-project/src/doc/manual/ref_guide_optimization.xml @@ -489,6 +489,22 @@ fields to be of type <classname>Set, SortedSet, HashSet,</classname> or <classname>TreeSet</classname>. </entry> </row> + <row> + <entry colname="name"> + <emphasis role="bold">Use query parameters instead of + encoding search data in filter strings</emphasis> + <para><emphasis>performance</emphasis></para> + </entry> + <entry colname="desc"> + If your queries depend on parameter data only known at + runtime, you should use query parameters rather than + dynamically building different query strings. OpenJPA + performs aggressive caching of query compilation + data, and the effectiveness of this cache is diminished if + multiple query filters are used where a single one could + have sufficed. + </entry> + </row> <row> <entry colname="name"> <emphasis role="bold">