Bugfix for when abstract base class has no discriminator value. Cleanup of

query compilation cache additions.



git-svn-id: https://svn.apache.org/repos/asf/incubator/openjpa/trunk@472275 13f79535-47bb-0310-9956-ffa450edef68
This commit is contained in:
A. Abram White 2006-11-07 21:20:57 +00:00
parent 0e02efdfbf
commit 3b9fa1f25a
9 changed files with 164 additions and 153 deletions

View File

@ -42,7 +42,6 @@ public class MappingRepositoryValue
// we need to manually perform the instantiation
try {
Class cls = Strings.toClass(clsName, type.getClassLoader());
return cls.getConstructor(new Class[]{ JDBCConfiguration.class }).
newInstance(new Object[]{ conf });
} catch (RuntimeException e) {

View File

@ -447,7 +447,8 @@ public class MappingDefaultsImpl
return UntypedPCValueHandler.getInstance();
if (_ordinalEnum && !vm.isSerialized()
&& JavaVersions.isEnumeration(type))
return "org.apache.openjpa.jdbc.meta.strats.EnumValueHandler(StoreOrdinal=true)";
return "org.apache.openjpa.jdbc.meta.strats.EnumValueHandler"
+ "(StoreOrdinal=true)";
return null;
}

View File

@ -34,10 +34,18 @@ public class SuperclassDiscriminatorStrategy
extends AbstractDiscriminatorStrategy {
public void map(boolean adapt) {
// if the superclass maps the discriminator value, so should we
if (disc.getClassMapping().getJoinablePCSuperclassMapping().
getDiscriminator().getValue() != null)
disc.setValue(disc.getMappingInfo().getValue(disc, adapt));
// if a superclass maps the discriminator value, so should we.
// otherwise assume it's calculated
ClassMapping sup = disc.getClassMapping().
getJoinablePCSuperclassMapping();
for (; sup != null; sup = sup.getJoinablePCSuperclassMapping()) {
if (sup.getDiscriminator().getValue() != null
|| sup.getDiscriminator().getStrategy() instanceof
ValueMapDiscriminatorStrategy) {
disc.setValue(disc.getMappingInfo().getValue(disc, adapt));
break;
}
}
}
public void loadSubclasses(JDBCStore store)

View File

@ -460,7 +460,10 @@ public class OpenJPAConfigurationImpl
compatibilityPlugin.setString(aliases[0]);
compatibilityPlugin.setInstantiatingGetter("getCompatibilityInstance");
queryCompilationCachePlugin = new QueryCompilationCacheValue(this);
queryCompilationCachePlugin = new QueryCompilationCacheValue(
"QueryCompilationCache");
queryCompilationCachePlugin.setInstantiatingGetter(
"getQueryCompilationCacheInstance");
addValue(queryCompilationCachePlugin);
// initialize supported options that some runtimes may not support
@ -1388,14 +1391,13 @@ public class OpenJPAConfigurationImpl
return queryCompilationCachePlugin.getString();
}
public void setQueryCompilationCache(String conf) {
queryCompilationCachePlugin.setString(conf);
public void setQueryCompilationCache(String queryCompilationCache) {
queryCompilationCachePlugin.setString(queryCompilationCache);
}
public Map getQueryCompilationCacheInstance() {
if (queryCompilationCachePlugin.get() == null)
queryCompilationCachePlugin.instantiate(
QueryCompilationCacheValue.class, this);
queryCompilationCachePlugin.instantiate(Map.class, this);
return (Map) queryCompilationCachePlugin.get();
}

View File

@ -15,14 +15,18 @@
*/
package org.apache.openjpa.conf;
import java.util.*;
import java.util.Collections;
import java.util.Hashtable;
import java.util.Map;
import org.apache.openjpa.lib.conf.*;
import org.apache.openjpa.lib.util.concurrent.*;
import org.apache.openjpa.util.*;
import org.apache.openjpa.lib.conf.Configuration;
import org.apache.openjpa.lib.conf.PluginValue;
import org.apache.openjpa.lib.util.concurrent.ConcurrentMap;
import org.apache.openjpa.lib.util.concurrent.ConcurrentHashMap;
import org.apache.openjpa.util.CacheMap;
/**
* <p>A cache of compiled queries.</p>
* A cache of compiled queries.
*
* @author Abe White
* @since 0.9.6 (also existed in prior versions of Kodo)
@ -31,35 +35,17 @@ import org.apache.openjpa.util.*;
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);
public QueryCompilationCacheValue(String prop) {
super(prop, 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,

View File

@ -527,6 +527,7 @@ public class QueryImpl
|| _broker == null)
return _params;
// check again after compilation; maybe encoded in string
compileForCompilation();
return _params;
} finally {
@ -562,6 +563,15 @@ public class QueryImpl
}
}
public Object getCompilation() {
lock();
try {
return compileForCompilation().storeData;
} finally {
unlock();
}
}
/**
* Compile query properties.
*/
@ -589,7 +599,8 @@ public class QueryImpl
}
/**
* Create and initialize a query compilation based on current data.
* Find the cached compilation for the current query, creating one if it
* does not exist.
*/
protected Compilation compilationFromCache() {
Map compCache =
@ -622,6 +633,9 @@ public class QueryImpl
}
}
/**
* Create and populate a new compilation.
*/
private Compilation newCompilation() {
Compilation comp = new Compilation();
comp.storeData = _storeQuery.newCompilation();
@ -1510,15 +1524,6 @@ public class QueryImpl
_lock.unlock();
}
public Object getCompilation() {
lock();
try {
return compileForCompilation().storeData;
} finally {
unlock();
}
}
/////////
// Utils
/////////
@ -1672,6 +1677,54 @@ public class QueryImpl
public Object storeData = null;
}
/**
* 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;
}
}
/**
* A merged executor executes multiple Queries and returns
* a merged result list with the appropriate ordering (if more than
@ -2077,52 +2130,4 @@ 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;
}
}
}

View File

@ -789,25 +789,31 @@ Iterator cachedIterator = extentQuery.getResultList().iterator();
</section>
</section>
<section id="ref_guide_cache_querycomp">
<title>Query Compilation Cache</title>
<title>
Query Compilation Cache
</title>
<indexterm zone="ref_guide_cache_querycomp">
<primary>caching</primary>
<secondary>query compilation cache</secondary>
<primary>
caching
</primary>
<secondary>
query compilation cache
</secondary>
</indexterm>
<para>
The query compilation cache is a <classname>Map</classname> 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
<link linkend="openjpa.QueryCompilationCache"><literal>
openjpa.QueryCompilationCache</literal></link> configuration property.
This property accepts a plugin string (see
<xref linkend="ref_guide_conf_plugins"/>) describing the
<classname>Map</classname> used to associate query strings and their
parsed form. This property accepts the following aliases:
The query compilation cache is a <classname>Map</classname> 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 <link linkend="openjpa.QueryCompilationCache"><literal>
openjpa.QueryCompilationCache</literal></link> configuration property. This
property accepts a plugin string (see <xref linkend="ref_guide_conf_plugins"/>)
describing the <classname>Map</classname> used to associate query strings and
their parsed form. This property accepts the following aliases:
</para>
<table>
<title>Pre-defined aliases</title>
<title>
Pre-defined aliases
</title>
<tgroup cols="2" align="left" colsep="1" rowsep="1">
<colspec colname="alias"/>
<colspec colname="value"/>
@ -822,44 +828,39 @@ Iterator cachedIterator = extentQuery.getResultList().iterator();
<tbody>
<row>
<entry colname="alias">
<literal>true</literal>
<literal>true</literal>
</entry>
<entry colname="value">
<literal>org.apache.openjpa.util.CacheMap</literal>
<literal>org.apache.openjpa.util.CacheMap</literal>
</entry>
<entry colname="notes">
The default option. Uses a
<ulink url="&javadoc-dir;/org/apache/openjpa/util/CacheMap.html">
<literal>CacheMap</literal></ulink> to store
compilation data. <literal>CacheMap</literal> 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.
The default option. Uses a
<ulink url="../javadoc/org/apache/openjpa/util/CacheMap.html">
<literal>CacheMap</literal></ulink> to store compilation data.
<literal>CacheMap</literal> maintains 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.
</entry>
</row>
<row>
<entry colname="alias"><literal>all</literal></entry>
<entry colname="value">
<literal>org.apache.openjpa.lib.util.ConcurrentHashMap</literal>
<literal>org.apache.openjpa.lib.util.ConcurrentHashMap</literal>
</entry>
<entry colname="notes">
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.
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.
</entry>
</row>
<row>
<entry colname="alias"><literal>false</literal></entry>
<entry colname="value"><emphasis>none</emphasis></entry>
<entry colname="notes">
Disables the compilation cache.
Disables the compilation cache.
</entry>
</row>
</tbody>

View File

@ -2455,31 +2455,38 @@ implementation to use for caching of queries loaded from the data store. See
</para>
</section>
<section id="openjpa.QueryCompilationCache">
<title>openjpa.QueryCompilationCache</title>
<title>
openjpa.QueryCompilationCache
</title>
<indexterm zone="openjpa.QueryCompilationCache">
<primary>QueryCompilationCache</primary>
<primary>
QueryCompilationCache
</primary>
</indexterm>
<indexterm zone="openjpa.QueryCompilationCache">
<primary>caching</primary>
<secondary>QueryCompilationCache</secondary>
<primary>
caching
</primary>
<secondary>
QueryCompilationCache
</secondary>
</indexterm>
<para>
<emphasis role="bold">Property name:</emphasis>
<literal>openjpa.QueryCompilationCache</literal>
<emphasis role="bold">Property name:</emphasis>
<literal>openjpa.QueryCompilationCache</literal>
</para>
<para>
<emphasis role="bold">Resource adaptor config-property:</emphasis>
<literal>QueryCompilationCache</literal>
<emphasis role="bold">Resource adaptor config-property:</emphasis>
<literal>QueryCompilationCache</literal>
</para>
<para>
<emphasis role="bold">Default:</emphasis> <literal>true</literal>.
<emphasis role="bold">Default:</emphasis> <literal>true</literal>.
</para>
<para>
<emphasis role="bold">Description:</emphasis> A plugin
string (see <xref linkend="ref_guide_conf_plugins"/>)
describing the <literal>java.util.Map</literal> to use for
caching of data used during query compilation.
See <xref linkend="ref_guide_cache_querycomp"/> for details.
<emphasis role="bold">Description:</emphasis> A plugin string (see
<xref linkend="ref_guide_conf_plugins"/>) describing the
<classname>java.util.Map</classname> to use for caching of data used during
query compilation. See <xref linkend="ref_guide_cache_querycomp"/> for details.
</para>
</section>
<section id="openjpa.ReadLockLevel">

View File

@ -491,18 +491,20 @@ fields to be of type <classname>Set, SortedSet, HashSet,</classname> or
</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>
<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.
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>