mirror of https://github.com/apache/openjpa.git
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:
parent
0e02efdfbf
commit
3b9fa1f25a
|
@ -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) {
|
||||
|
|
|
@ -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;
|
||||
}
|
||||
|
||||
|
|
|
@ -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)
|
||||
|
|
|
@ -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();
|
||||
}
|
||||
|
||||
|
|
|
@ -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,
|
||||
|
|
|
@ -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;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -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>
|
||||
|
|
|
@ -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">
|
||||
|
|
|
@ -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>
|
||||
|
|
Loading…
Reference in New Issue