You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@openjpa.apache.org by pp...@apache.org on 2008/09/09 04:03:38 UTC
svn commit: r693341 [2/2] - in /openjpa/branches/sql-cache:
openjpa-jdbc/src/main/java/org/apache/openjpa/jdbc/kernel/
openjpa-jdbc/src/main/java/org/apache/openjpa/jdbc/kernel/exps/
openjpa-jdbc/src/main/java/org/apache/openjpa/jdbc/sql/ openjpa-kerne...
Modified: openjpa/branches/sql-cache/openjpa-persistence/src/main/java/org/apache/openjpa/persistence/EntityManagerFactoryImpl.java
URL: http://svn.apache.org/viewvc/openjpa/branches/sql-cache/openjpa-persistence/src/main/java/org/apache/openjpa/persistence/EntityManagerFactoryImpl.java?rev=693341&r1=693340&r2=693341&view=diff
==============================================================================
--- openjpa/branches/sql-cache/openjpa-persistence/src/main/java/org/apache/openjpa/persistence/EntityManagerFactoryImpl.java (original)
+++ openjpa/branches/sql-cache/openjpa-persistence/src/main/java/org/apache/openjpa/persistence/EntityManagerFactoryImpl.java Mon Sep 8 19:03:37 2008
@@ -1,335 +1,358 @@
-/*
- * 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.persistence;
-
-import java.lang.reflect.Constructor;
-import java.lang.reflect.InvocationTargetException;
-import java.lang.reflect.Method;
-import java.util.Collections;
-import java.util.HashMap;
-import java.util.LinkedList;
-import java.util.List;
-import java.util.Map;
-import java.util.Properties;
-import java.util.Set;
-import javax.persistence.EntityManagerFactory;
-
-import org.apache.openjpa.conf.OpenJPAConfiguration;
-import org.apache.openjpa.enhance.Reflection;
-import org.apache.openjpa.kernel.AutoDetach;
-import org.apache.openjpa.kernel.Broker;
-import org.apache.openjpa.kernel.BrokerFactory;
-import org.apache.openjpa.kernel.DelegatingBrokerFactory;
-import org.apache.openjpa.kernel.DelegatingFetchConfiguration;
-import org.apache.openjpa.kernel.FetchConfiguration;
-import org.apache.openjpa.lib.conf.Configurations;
-import org.apache.openjpa.lib.conf.ProductDerivations;
-import org.apache.openjpa.lib.conf.Value;
-import org.apache.openjpa.lib.util.Localizer;
-import org.apache.openjpa.lib.util.Closeable;
-import org.apache.openjpa.util.OpenJPAException;
-import serp.util.Strings;
-
-/**
- * Implementation of {@link EntityManagerFactory} that acts as a
- * facade to a {@link BrokerFactory}.
- *
- * @author Marc Prud'hommeaux
- * @nojavadoc
- */
-public class EntityManagerFactoryImpl
- implements OpenJPAEntityManagerFactory, OpenJPAEntityManagerFactorySPI,
- Closeable {
-
- private static final Localizer _loc = Localizer.forPackage
- (EntityManagerFactoryImpl.class);
-
- private DelegatingBrokerFactory _factory = null;
- private transient Constructor<FetchPlan> _plan = null;
- private transient StoreCache _cache = null;
- private transient QueryResultCache _queryCache = null;
-
- /**
- * Default constructor provided for auto-instantiation.
- */
- public EntityManagerFactoryImpl() {
- }
-
- /**
- * Supply delegate on construction.
- */
- public EntityManagerFactoryImpl(BrokerFactory factory) {
- setBrokerFactory(factory);
- }
-
- /**
- * Delegate.
- */
- public BrokerFactory getBrokerFactory() {
- return _factory.getDelegate();
- }
-
- /**
- * Delegate must be provided before use.
- */
- public void setBrokerFactory(BrokerFactory factory) {
- _factory = new DelegatingBrokerFactory(factory,
- PersistenceExceptions.TRANSLATOR);
- }
-
- public OpenJPAConfiguration getConfiguration() {
- return _factory.getConfiguration();
- }
-
- public Properties getProperties() {
- return _factory.getProperties();
- }
-
- public Object putUserObject(Object key, Object val) {
- return _factory.putUserObject(key, val);
- }
-
- public Object getUserObject(Object key) {
- return _factory.getUserObject(key);
- }
-
- public StoreCache getStoreCache() {
- _factory.lock();
- try {
- if (_cache == null) {
- OpenJPAConfiguration conf = _factory.getConfiguration();
- _cache = new StoreCacheImpl(this,
- conf.getDataCacheManagerInstance().getSystemDataCache());
- }
- return _cache;
- } finally {
- _factory.unlock();
- }
- }
-
- public StoreCache getStoreCache(String cacheName) {
- return new StoreCacheImpl(this, _factory.getConfiguration().
- getDataCacheManagerInstance().getDataCache(cacheName, true));
- }
-
- public QueryResultCache getQueryResultCache() {
- _factory.lock();
- try {
- if (_queryCache == null)
- _queryCache = new QueryResultCacheImpl(_factory.
- getConfiguration().getDataCacheManagerInstance().
- getSystemQueryCache());
- return _queryCache;
- } finally {
- _factory.unlock();
- }
- }
-
- public OpenJPAEntityManagerSPI createEntityManager() {
- return createEntityManager(null);
- }
-
- public OpenJPAEntityManagerSPI createEntityManager(Map props) {
- if (props == null)
- props = Collections.EMPTY_MAP;
- else if (!props.isEmpty())
- props = new HashMap(props);
-
- OpenJPAConfiguration conf = getConfiguration();
- String user = (String) Configurations.removeProperty
- ("ConnectionUserName", props);
- if (user == null)
- user = conf.getConnectionUserName();
- String pass = (String) Configurations.removeProperty
- ("ConnectionPassword", props);
- if (pass == null)
- pass = conf.getConnectionPassword();
-
- String str = (String) Configurations.removeProperty
- ("TransactionMode", props);
- boolean managed;
- if (str == null)
- managed = conf.isTransactionModeManaged();
- else {
- Value val = conf.getValue("TransactionMode");
- managed = Boolean.parseBoolean(val.unalias(str));
- }
-
- Object obj = Configurations.removeProperty("ConnectionRetainMode",
- props);
- int retainMode;
- if (obj instanceof Number)
- retainMode = ((Number) obj).intValue();
- else if (obj == null)
- retainMode = conf.getConnectionRetainModeConstant();
- else {
- Value val = conf.getValue("ConnectionRetainMode");
- try {
- retainMode = Integer.parseInt(val.unalias((String) obj));
- } catch (Exception e) {
- throw new ArgumentException(_loc.get("bad-em-prop",
- "openjpa.ConnectionRetainMode", obj),
- new Throwable[]{ e }, obj, true);
- }
- }
-
- Broker broker = _factory.newBroker(user, pass, managed, retainMode,
- false);
-
- // add autodetach for close and rollback conditions to the configuration
- broker.setAutoDetach(AutoDetach.DETACH_CLOSE, true);
- broker.setAutoDetach(AutoDetach.DETACH_ROLLBACK, true);
-
- broker.setDetachedNew(false);
- OpenJPAEntityManagerSPI em = newEntityManagerImpl(broker);
-
- // allow setting of other bean properties of EM
- String[] prefixes = ProductDerivations.getConfigurationPrefixes();
- List<RuntimeException> errs = null;
- Method setter;
- String prop, prefix;
- Object val;
- for (Map.Entry entry : (Set<Map.Entry>) props.entrySet()) {
- prop = (String) entry.getKey();
- prefix = null;
- for (int i = 0; i < prefixes.length; i++) {
- prefix = prefixes[i] + ".";
- if (prop.startsWith(prefix))
- break;
- prefix = null;
- }
- if (prefix == null)
- continue;
- prop = prop.substring(prefix.length());
- try {
- setter = Reflection.findSetter(em.getClass(), prop, true);
- } catch (OpenJPAException ke) {
- if (errs == null)
- errs = new LinkedList<RuntimeException>();
- errs.add(PersistenceExceptions.toPersistenceException(ke));
- continue;
- }
-
- val = entry.getValue();
- try {
- if (val instanceof String) {
- if ("null".equals(val))
- val = null;
- else
- val = Strings.parse((String) val,
- setter.getParameterTypes()[0]);
- }
- Reflection.set(em, setter, val);
- } catch (Throwable t) {
- while (t.getCause() != null)
- t = t.getCause();
- ArgumentException err = new ArgumentException(_loc.get
- ("bad-em-prop", prop, entry.getValue()),
- new Throwable[]{ t }, null, true);
- if (errs == null)
- errs = new LinkedList<RuntimeException>();
- errs.add(err);
- }
- }
-
- if (errs != null) {
- em.close();
- if (errs.size() == 1)
- throw errs.get(0);
- throw new ArgumentException(_loc.get("bad-em-props"),
- errs.toArray(new Throwable[errs.size()]),
- null, true);
- }
- return em;
- }
-
- /**
- * Create a new entity manager around the given broker.
- */
- protected EntityManagerImpl newEntityManagerImpl(Broker broker) {
- return new EntityManagerImpl(this, broker);
- }
-
- public void addLifecycleListener(Object listener, Class... classes) {
- _factory.addLifecycleListener(listener, classes);
- }
-
- public void removeLifecycleListener(Object listener) {
- _factory.removeLifecycleListener(listener);
- }
-
- public void addTransactionListener(Object listener) {
- _factory.addTransactionListener(listener);
- }
-
- public void removeTransactionListener(Object listener) {
- _factory.removeTransactionListener(listener);
- }
-
- public void close() {
- _factory.close();
- }
-
- public boolean isOpen() {
- return !_factory.isClosed();
- }
-
- public int hashCode() {
- return _factory.hashCode();
- }
-
- public boolean equals(Object other) {
- if (other == this)
- return true;
- if (!(other instanceof EntityManagerFactoryImpl))
- return false;
- return _factory.equals(((EntityManagerFactoryImpl) other)._factory);
- }
-
- /**
- * Create a store-specific facade for the given fetch configuration.
- * If no facade class exists, we use the default {@link FetchPlan}.
- */
- FetchPlan toFetchPlan(Broker broker, FetchConfiguration fetch) {
- if (fetch == null)
- return null;
-
- if (fetch instanceof DelegatingFetchConfiguration)
- fetch = ((DelegatingFetchConfiguration) fetch).
- getInnermostDelegate();
-
- try {
- if (_plan == null) {
- Class storeType = (broker == null) ? null : broker.
- getStoreManager().getInnermostDelegate().getClass();
- Class cls = _factory.getConfiguration().
- getStoreFacadeTypeRegistry().
- getImplementation(FetchPlan.class, storeType,
- FetchPlanImpl.class);
- _plan = cls.getConstructor(FetchConfiguration.class);
- }
- return _plan.newInstance(fetch);
- } catch (InvocationTargetException ite) {
- throw PersistenceExceptions.toPersistenceException
- (ite.getTargetException());
- } catch (Exception e) {
- throw PersistenceExceptions.toPersistenceException(e);
- }
- }
-}
+/*
+ * 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.persistence;
+
+import java.lang.reflect.Constructor;
+import java.lang.reflect.InvocationTargetException;
+import java.lang.reflect.Method;
+import java.util.Collections;
+import java.util.HashMap;
+import java.util.LinkedList;
+import java.util.List;
+import java.util.Map;
+import java.util.Properties;
+import java.util.Set;
+import java.util.concurrent.ConcurrentHashMap;
+
+import javax.persistence.EntityManagerFactory;
+
+import org.apache.openjpa.conf.OpenJPAConfiguration;
+import org.apache.openjpa.enhance.Reflection;
+import org.apache.openjpa.kernel.AutoDetach;
+import org.apache.openjpa.kernel.Broker;
+import org.apache.openjpa.kernel.BrokerFactory;
+import org.apache.openjpa.kernel.DelegatingBrokerFactory;
+import org.apache.openjpa.kernel.DelegatingFetchConfiguration;
+import org.apache.openjpa.kernel.FetchConfiguration;
+import org.apache.openjpa.lib.conf.Configurations;
+import org.apache.openjpa.lib.conf.ProductDerivations;
+import org.apache.openjpa.lib.conf.Value;
+import org.apache.openjpa.lib.util.Closeable;
+import org.apache.openjpa.lib.util.Localizer;
+import org.apache.openjpa.util.OpenJPAException;
+
+import serp.util.Strings;
+
+/**
+ * Implementation of {@link EntityManagerFactory} that acts as a
+ * facade to a {@link BrokerFactory}.
+ *
+ * @author Marc Prud'hommeaux
+ * @nojavadoc
+ */
+public class EntityManagerFactoryImpl
+ implements OpenJPAEntityManagerFactory, OpenJPAEntityManagerFactorySPI,
+ Closeable {
+
+ private static final Localizer _loc = Localizer.forPackage
+ (EntityManagerFactoryImpl.class);
+
+ private DelegatingBrokerFactory _factory = null;
+ private transient Constructor<FetchPlan> _plan = null;
+ private transient StoreCache _cache = null;
+ private transient QueryResultCache _queryCache = null;
+ private transient Map<String, PreparedQuery> _sqlQueryCache = null;
+
+ /**
+ * Default constructor provided for auto-instantiation.
+ */
+ public EntityManagerFactoryImpl() {
+ }
+
+ /**
+ * Supply delegate on construction.
+ */
+ public EntityManagerFactoryImpl(BrokerFactory factory) {
+ setBrokerFactory(factory);
+ }
+
+ /**
+ * Delegate.
+ */
+ public BrokerFactory getBrokerFactory() {
+ return _factory.getDelegate();
+ }
+
+ /**
+ * Delegate must be provided before use.
+ */
+ public void setBrokerFactory(BrokerFactory factory) {
+ _factory = new DelegatingBrokerFactory(factory,
+ PersistenceExceptions.TRANSLATOR);
+ }
+
+ public OpenJPAConfiguration getConfiguration() {
+ return _factory.getConfiguration();
+ }
+
+ public Properties getProperties() {
+ return _factory.getProperties();
+ }
+
+ public Object putUserObject(Object key, Object val) {
+ return _factory.putUserObject(key, val);
+ }
+
+ public Object getUserObject(Object key) {
+ return _factory.getUserObject(key);
+ }
+
+ public StoreCache getStoreCache() {
+ _factory.lock();
+ try {
+ if (_cache == null) {
+ OpenJPAConfiguration conf = _factory.getConfiguration();
+ _cache = new StoreCacheImpl(this,
+ conf.getDataCacheManagerInstance().getSystemDataCache());
+ }
+ return _cache;
+ } finally {
+ _factory.unlock();
+ }
+ }
+
+ public StoreCache getStoreCache(String cacheName) {
+ return new StoreCacheImpl(this, _factory.getConfiguration().
+ getDataCacheManagerInstance().getDataCache(cacheName, true));
+ }
+
+ public QueryResultCache getQueryResultCache() {
+ _factory.lock();
+ try {
+ if (_queryCache == null)
+ _queryCache = new QueryResultCacheImpl(_factory.
+ getConfiguration().getDataCacheManagerInstance().
+ getSystemQueryCache());
+ return _queryCache;
+ } finally {
+ _factory.unlock();
+ }
+ }
+
+ public OpenJPAEntityManagerSPI createEntityManager() {
+ return createEntityManager(null);
+ }
+
+ public OpenJPAEntityManagerSPI createEntityManager(Map props) {
+ if (props == null)
+ props = Collections.EMPTY_MAP;
+ else if (!props.isEmpty())
+ props = new HashMap(props);
+
+ OpenJPAConfiguration conf = getConfiguration();
+ String user = (String) Configurations.removeProperty
+ ("ConnectionUserName", props);
+ if (user == null)
+ user = conf.getConnectionUserName();
+ String pass = (String) Configurations.removeProperty
+ ("ConnectionPassword", props);
+ if (pass == null)
+ pass = conf.getConnectionPassword();
+
+ String str = (String) Configurations.removeProperty
+ ("TransactionMode", props);
+ boolean managed;
+ if (str == null)
+ managed = conf.isTransactionModeManaged();
+ else {
+ Value val = conf.getValue("TransactionMode");
+ managed = Boolean.parseBoolean(val.unalias(str));
+ }
+
+ Object obj = Configurations.removeProperty("ConnectionRetainMode",
+ props);
+ int retainMode;
+ if (obj instanceof Number)
+ retainMode = ((Number) obj).intValue();
+ else if (obj == null)
+ retainMode = conf.getConnectionRetainModeConstant();
+ else {
+ Value val = conf.getValue("ConnectionRetainMode");
+ try {
+ retainMode = Integer.parseInt(val.unalias((String) obj));
+ } catch (Exception e) {
+ throw new ArgumentException(_loc.get("bad-em-prop",
+ "openjpa.ConnectionRetainMode", obj),
+ new Throwable[]{ e }, obj, true);
+ }
+ }
+
+ Broker broker = _factory.newBroker(user, pass, managed, retainMode,
+ false);
+
+ // add autodetach for close and rollback conditions to the configuration
+ broker.setAutoDetach(AutoDetach.DETACH_CLOSE, true);
+ broker.setAutoDetach(AutoDetach.DETACH_ROLLBACK, true);
+
+ broker.setDetachedNew(false);
+ OpenJPAEntityManagerSPI em = newEntityManagerImpl(broker);
+
+ // allow setting of other bean properties of EM
+ String[] prefixes = ProductDerivations.getConfigurationPrefixes();
+ List<RuntimeException> errs = null;
+ Method setter;
+ String prop, prefix;
+ Object val;
+ for (Map.Entry entry : (Set<Map.Entry>) props.entrySet()) {
+ prop = (String) entry.getKey();
+ prefix = null;
+ for (int i = 0; i < prefixes.length; i++) {
+ prefix = prefixes[i] + ".";
+ if (prop.startsWith(prefix))
+ break;
+ prefix = null;
+ }
+ if (prefix == null)
+ continue;
+ prop = prop.substring(prefix.length());
+ try {
+ setter = Reflection.findSetter(em.getClass(), prop, true);
+ } catch (OpenJPAException ke) {
+ if (errs == null)
+ errs = new LinkedList<RuntimeException>();
+ errs.add(PersistenceExceptions.toPersistenceException(ke));
+ continue;
+ }
+
+ val = entry.getValue();
+ try {
+ if (val instanceof String) {
+ if ("null".equals(val))
+ val = null;
+ else
+ val = Strings.parse((String) val,
+ setter.getParameterTypes()[0]);
+ }
+ Reflection.set(em, setter, val);
+ } catch (Throwable t) {
+ while (t.getCause() != null)
+ t = t.getCause();
+ ArgumentException err = new ArgumentException(_loc.get
+ ("bad-em-prop", prop, entry.getValue()),
+ new Throwable[]{ t }, null, true);
+ if (errs == null)
+ errs = new LinkedList<RuntimeException>();
+ errs.add(err);
+ }
+ }
+
+ if (errs != null) {
+ em.close();
+ if (errs.size() == 1)
+ throw errs.get(0);
+ throw new ArgumentException(_loc.get("bad-em-props"),
+ errs.toArray(new Throwable[errs.size()]),
+ null, true);
+ }
+ return em;
+ }
+
+ /**
+ * Create a new entity manager around the given broker.
+ */
+ protected EntityManagerImpl newEntityManagerImpl(Broker broker) {
+ return new EntityManagerImpl(this, broker);
+ }
+
+ public void addLifecycleListener(Object listener, Class... classes) {
+ _factory.addLifecycleListener(listener, classes);
+ }
+
+ public void removeLifecycleListener(Object listener) {
+ _factory.removeLifecycleListener(listener);
+ }
+
+ public void addTransactionListener(Object listener) {
+ _factory.addTransactionListener(listener);
+ }
+
+ public void removeTransactionListener(Object listener) {
+ _factory.removeTransactionListener(listener);
+ }
+
+ public void close() {
+ _factory.close();
+ }
+
+ public boolean isOpen() {
+ return !_factory.isClosed();
+ }
+
+ public int hashCode() {
+ return _factory.hashCode();
+ }
+
+ public boolean equals(Object other) {
+ if (other == this)
+ return true;
+ if (!(other instanceof EntityManagerFactoryImpl))
+ return false;
+ return _factory.equals(((EntityManagerFactoryImpl) other)._factory);
+ }
+
+ /**
+ * Create a store-specific facade for the given fetch configuration.
+ * If no facade class exists, we use the default {@link FetchPlan}.
+ */
+ FetchPlan toFetchPlan(Broker broker, FetchConfiguration fetch) {
+ if (fetch == null)
+ return null;
+
+ if (fetch instanceof DelegatingFetchConfiguration)
+ fetch = ((DelegatingFetchConfiguration) fetch).
+ getInnermostDelegate();
+
+ try {
+ if (_plan == null) {
+ Class storeType = (broker == null) ? null : broker.
+ getStoreManager().getInnermostDelegate().getClass();
+ Class cls = _factory.getConfiguration().
+ getStoreFacadeTypeRegistry().
+ getImplementation(FetchPlan.class, storeType,
+ FetchPlanImpl.class);
+ _plan = cls.getConstructor(FetchConfiguration.class);
+ }
+ return _plan.newInstance(fetch);
+ } catch (InvocationTargetException ite) {
+ throw PersistenceExceptions.toPersistenceException
+ (ite.getTargetException());
+ } catch (Exception e) {
+ throw PersistenceExceptions.toPersistenceException(e);
+ }
+ }
+
+// boolean cacheQuery(String qid, PreparedQuery sql) {
+// if (!isCacheingSQL())
+// return false;
+// if (_sqlQueryCache == null)
+// _sqlQueryCache = new ConcurrentHashMap<String, PreparedQuery>();
+// _sqlQueryCache.put(qid, sql);
+// return true;
+// }
+//
+// PreparedQuery getPreparedQuery(String qid) {
+// if (!isCacheingSQL())
+// return null;
+// if (_sqlQueryCache == null)
+// return null;
+// PreparedQuery result = _sqlQueryCache.get(qid);
+// return result;
+// }
+
+}
Modified: openjpa/branches/sql-cache/openjpa-persistence/src/main/java/org/apache/openjpa/persistence/EntityManagerImpl.java
URL: http://svn.apache.org/viewvc/openjpa/branches/sql-cache/openjpa-persistence/src/main/java/org/apache/openjpa/persistence/EntityManagerImpl.java?rev=693341&r1=693340&r2=693341&view=diff
==============================================================================
--- openjpa/branches/sql-cache/openjpa-persistence/src/main/java/org/apache/openjpa/persistence/EntityManagerImpl.java (original)
+++ openjpa/branches/sql-cache/openjpa-persistence/src/main/java/org/apache/openjpa/persistence/EntityManagerImpl.java Mon Sep 8 19:03:37 2008
@@ -64,6 +64,7 @@
import org.apache.openjpa.meta.SequenceMetaData;
import org.apache.openjpa.util.Exceptions;
import org.apache.openjpa.util.ImplHelper;
+import org.apache.openjpa.util.ParameterMap;
import org.apache.openjpa.util.RuntimeExceptionTranslator;
import org.apache.openjpa.util.UserException;
@@ -868,12 +869,21 @@
public OpenJPAQuery createQuery(String language, String query) {
assertNotCloseInvoked();
try {
+ String qid = query;
+ PreparedQuery cached = getPreparedQuery(qid);
+ if (cached != null) {
+ language = QueryLanguages.LANG_PREPARED_SQL;
+ query = cached.getSQL();
+ }
org.apache.openjpa.kernel.Query q = _broker.newQuery(language,
query);
// have to validate JPQL according to spec
if (JPQLParser.LANG_JPQL.equals(language))
q.compile();
- return new QueryImpl(this, _ret, q);
+ if (cached != null) {
+ cached.setInto(q);
+ }
+ return new QueryImpl(this, _ret, q).setId(qid);
} catch (RuntimeException re) {
throw PersistenceExceptions.toPersistenceException(re);
}
@@ -936,6 +946,16 @@
if (StringUtils.trimToNull(query) == null)
throw new ArgumentException(_loc.get("no-sql"), null, null, false);
}
+
+ private PreparedQuery getPreparedQuery(String id) {
+ Map cache = getConfiguration().getPreparedQueryCacheInstance();
+ if (cache == null)
+ return null;
+ Object val = cache.get(id);
+ if (val == PreparedQuery.NOT_CACHABLE)
+ return null;
+ return (PreparedQuery)val;
+ }
public void setFlushMode(FlushModeType flushMode) {
assertNotCloseInvoked();
Added: openjpa/branches/sql-cache/openjpa-persistence/src/main/java/org/apache/openjpa/persistence/PreparedQuery.java
URL: http://svn.apache.org/viewvc/openjpa/branches/sql-cache/openjpa-persistence/src/main/java/org/apache/openjpa/persistence/PreparedQuery.java?rev=693341&view=auto
==============================================================================
--- openjpa/branches/sql-cache/openjpa-persistence/src/main/java/org/apache/openjpa/persistence/PreparedQuery.java (added)
+++ openjpa/branches/sql-cache/openjpa-persistence/src/main/java/org/apache/openjpa/persistence/PreparedQuery.java Mon Sep 8 19:03:37 2008
@@ -0,0 +1,87 @@
+/*
+ * 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.persistence;
+
+import org.apache.openjpa.kernel.Query;
+
+/**
+ * A prepared query binds a compiled query to its target SQL.
+ *
+ * The target SQL is meant to be executed directly bypassing the critical
+ * cost of constructing the SQL on every query execution. As the subsequent
+ * execution of a cached query will bypass compilation as a JPQL query,
+ * the post-compilation state of the original query is captured in this receiver
+ * to be transferred to the executable query instance.
+ *
+ * @author Pinaki Poddar
+ *
+ */
+public class PreparedQuery {
+ public static final PreparedQuery NOT_CACHABLE = new PreparedQuery();
+ private final String _sql;
+ private final String _id;
+
+ // Post-compilation state of an executable query
+ Class _candidate = null;
+ boolean _subclasses = true;
+ boolean _isProjection = false;
+
+ private PreparedQuery() {
+ _sql = null;
+ _id = null;
+ }
+
+ public PreparedQuery(String id, String sql, Query compiled) {
+ this._id = id;
+ this._sql = sql;
+
+ _candidate = compiled.getCandidateType();
+ _subclasses = compiled.hasSubclasses();
+ _isProjection = compiled.getProjectionAliases().length > 0;
+ }
+
+ public String getIdentifier() {
+ return _id;
+ }
+
+ public String getSQL() {
+ return _sql;
+ }
+
+ public String toString() {
+ return "PreparedQuery " + _id + "==>" + _sql;
+ }
+
+ void setInto(Query q) {
+// q.setCandidateCollection(last.getCandidateCollection());
+// q.setCandidateExtent(last.getCandidateExtent());
+
+ if (!_isProjection)
+ q.setCandidateType(_candidate, _subclasses);
+
+// q.setIgnoreChanges(last.getIgnoreChanges());
+// q.setRange(last.getStartRange(), last.getEndRange());
+// q.setReadOnly(last.isReadOnly());
+// q.setResultMapping(last.getResultMappingScope(), last.getResultMappingName());
+// q.setResultType(last.getResultType());
+// q.setUnique(last.isUnique());
+ }
+
+
+}
Modified: openjpa/branches/sql-cache/openjpa-persistence/src/main/java/org/apache/openjpa/persistence/QueryImpl.java
URL: http://svn.apache.org/viewvc/openjpa/branches/sql-cache/openjpa-persistence/src/main/java/org/apache/openjpa/persistence/QueryImpl.java?rev=693341&r1=693340&r2=693341&view=diff
==============================================================================
--- openjpa/branches/sql-cache/openjpa-persistence/src/main/java/org/apache/openjpa/persistence/QueryImpl.java (original)
+++ openjpa/branches/sql-cache/openjpa-persistence/src/main/java/org/apache/openjpa/persistence/QueryImpl.java Mon Sep 8 19:03:37 2008
@@ -22,18 +22,13 @@
import java.lang.reflect.Method;
import java.sql.Time;
import java.sql.Timestamp;
-import java.util.ArrayList;
-import java.util.Arrays;
import java.util.Calendar;
import java.util.Collection;
import java.util.Collections;
import java.util.Date;
-import java.util.HashMap;
-import java.util.Iterator;
import java.util.List;
import java.util.Map;
import java.util.Set;
-import java.util.TreeMap;
import javax.persistence.FlushModeType;
import javax.persistence.Query;
@@ -51,13 +46,16 @@
import org.apache.openjpa.lib.rop.ResultList;
import org.apache.openjpa.lib.util.Localizer;
import org.apache.openjpa.util.ImplHelper;
+import org.apache.openjpa.util.ParameterMap;
import org.apache.openjpa.util.RuntimeExceptionTranslator;
+import org.apache.openjpa.util.UserException;
/**
* Implementation of {@link Query} interface.
*
* @author Marc Prud'hommeaux
* @author Abe White
+ * @author Pinaki Poddar
* @nojavadoc
*/
public class QueryImpl implements OpenJPAQuerySPI, Serializable {
@@ -69,17 +67,16 @@
private final DelegatingQuery _query;
private transient EntityManagerImpl _em;
private transient FetchPlan _fetch;
+ private ParameterMap _params;
+ private transient Boolean _cacheable = null;
+ private String _id;
- private Map<String, Object> _named;
- private Map<Integer, Object> _positional;
-
- private static Object GAP_FILLER = new Object();
/**
* Constructor; supply factory exception translator and delegate.
*
* @param em The EntityManager which created this query
- * @param ret Exception translater for this query
+ * @param ret Exception translator for this query
* @param query The underlying "kernel" query.
*/
public QueryImpl(EntityManagerImpl em, RuntimeExceptionTranslator ret,
@@ -246,183 +243,13 @@
if (_query.getOperation() != QueryOperations.OP_SELECT)
throw new InvalidStateException(_loc.get("not-select-query", _query
.getQueryString()), null, null, false);
-
- validateParameters();
-
- // handle which types of parameters we are using, if any
- if (_positional != null)
- return _query.execute(_positional);
- if (_named != null)
- return _query.execute(_named);
- return _query.execute();
+ PreparedQuery cachedQuery = cache();
+ boolean usingCachedQuery = (cachedQuery != null);
+ validate(_query.getParameterTypes(), !usingCachedQuery);
+ Object result = _query.execute(getParameterMap(usingCachedQuery));
+ return result;
}
- /**
- * Validate that the types of the parameters are correct.
- * The idea is to catch as many validation error as possible at the facade
- * layer itself.
- * For native SQL queries, however, parameter validation is bypassed as
- * we do not parse SQL.
- *
- * The expected parameters are parsed from the query and in a LinkedMap
- * key : name of the parameter as declared in query
- * value : expected Class of allowed value
- *
- * The bound parameters depends on positional or named parameter style
- *
- * TreeMap<Integer, Object> for positional parameters:
- * key : 1-based Integer index
- * value : bound value. GAP_FILLER if the position is not set. This
- * simplifies validation at the kernel layer
- *
- * Map<String, Object> for named parameters:
- * key : parameter name
- * value : the bound value
- *
- * Validation accounts for
- * a) gaps in positional parameters
- * SELECT p FROM PObject p WHERE p.a1=?1 AND p.a3=?3
- *
- * b) repeated parameters
- * SELECT p FROM PObject p WHERE p.a1=?1 AND p.a2=?1 AND p.a3=?2
- *
- * c) parameter is bound but not declared
- *
- * d) parameter is declared but not bound
- *
- * e) parameter does not match the value type
- *
- * f) parameter is primitive type but bound to null value
- */
- private void validateParameters() {
- if (isNative()) {
- removeGaps(_positional);
- return;
- }
- String query = getQueryString();
- if (_positional != null) {
- LinkedMap expected = _query.getParameterTypes();
- Map<Integer, Object> actual = _positional;
- for (Object o : expected.keySet()) {
- String position = (String) o;
- Class expectedParamType = (Class) expected.get(position);
- try {
- Integer.parseInt(position);
- } catch (NumberFormatException ex) {
- newValidationException("param-style-mismatch", query,
- expected.asList(),
- Arrays.toString(actual.keySet().toArray()));
- }
- Object actualValue = actual.get(Integer.parseInt(position));
- boolean valueUnspecified = (actualValue == GAP_FILLER)
- || (actualValue == null && (actual.size() < expected
- .size()));
- if (valueUnspecified)
- newValidationException("param-missing", position, query,
- Arrays.toString(actual.keySet().toArray()));
-
- if (expectedParamType.isPrimitive() && actualValue == null)
- newValidationException("param-type-null",
- position, query, expectedParamType.getName());
- if (actualValue != null &&
- !Filters.wrap(expectedParamType).isInstance(actualValue))
- newValidationException("param-type-mismatch",
- position, query, actualValue,
- actualValue.getClass().getName(),
- expectedParamType.getName());
-
- }
- for (Integer position : actual.keySet()) {
- Object actualValue = actual.get(position);
- Class expectedParamType = (Class) expected.get("" + position);
- boolean paramExpected = expected.containsKey("" + position);
- if (actualValue == GAP_FILLER) {
- if (paramExpected) {
- newValidationException("param-missing", position, query,
- Arrays.toString(actual.keySet().toArray()));
- }
- } else {
- if (!paramExpected)
- newValidationException("param-extra", position, query,
- expected.asList());
- if (expectedParamType.isPrimitive() && actualValue == null)
- newValidationException("param-type-null",
- position, query, expectedParamType.getName());
- if (actualValue != null
- && !Filters.wrap(expectedParamType).isInstance(actualValue))
- newValidationException("param-type-mismatch",
- position, query, actualValue,
- actualValue.getClass().getName(),
- expectedParamType.getName());
-
- }
- }
-
- } else if (_named != null) {
- LinkedMap expected = _query.getParameterTypes();
- // key : name of the parameter used while binding
- // value : user supplied parameter value. null may mean either
- // user has supplied a value or not specified at all
- Map<String, Object> actual = _named;
- for (Object o : expected.keySet()) {
- String expectedName = (String) o;
- Class expectedParamType = (Class) expected.get(expectedName);
- Object actualValue = actual.get(expectedName);
- boolean valueUnspecified = !actual.containsKey(expectedName);
- if (valueUnspecified) {
- newValidationException("param-missing", expectedName, query,
- Arrays.toString(actual.keySet().toArray()));
- }
- if (expectedParamType.isPrimitive() && actualValue == null)
- newValidationException("param-type-null",
- expectedName, query, expectedParamType.getName());
- if (actualValue != null
- && !Filters.wrap(expectedParamType).isInstance(actualValue)) {
- newValidationException("param-type-mismatch",
- expectedName, query, actualValue,
- actualValue.getClass().getName(),
- expectedParamType.getName());
- }
- }
- for (String actualName : actual.keySet()) {
- Object actualValue = actual.get(actualName);
- Class expectedParamType = (Class) expected.get(actualName);
- boolean paramExpected = expected.containsKey(actualName);
- if (!paramExpected) {
- newValidationException("param-extra", actualName, query,
- expected.asList());
- }
- if (expectedParamType.isPrimitive() && actualValue == null)
- newValidationException("param-type-null",
- actualName, query, expectedParamType.getName());
- if (actualValue != null
- && !Filters.wrap(expectedParamType).isInstance(actualValue)) {
- newValidationException("param-type-mismatch",
- actualName, query, actualValue,
- actualValue.getClass().getName(),
- expectedParamType.getName());
- }
- }
- }
- }
-
- Map<Integer, Object> removeGaps(Map<Integer, Object> map) {
- if (map == null || !map.containsValue(GAP_FILLER))
- return map;
- List<Integer> gaps = new ArrayList<Integer>();
- for (Integer key : map.keySet())
- if (map.get(key) == GAP_FILLER)
- gaps.add(key);
- for (Integer gap : gaps) {
- map.remove(gap);
- }
- return map;
- }
-
- void newValidationException(String msgKey, Object...args) {
- throw new ArgumentException(_loc.get(msgKey, args), null, null, false);
- }
-
public List getResultList() {
_em.assertNotCloseInvoked();
Object ob = execute();
@@ -457,20 +284,10 @@
public int executeUpdate() {
_em.assertNotCloseInvoked();
if (_query.getOperation() == QueryOperations.OP_DELETE) {
- // handle which types of parameters we are using, if any
- if (_positional != null)
- return asInt(_query.deleteAll(_positional));
- if (_named != null)
- return asInt(_query.deleteAll(_named));
- return asInt(_query.deleteAll());
+ return asInt(_query.deleteAll(_params));
}
if (_query.getOperation() == QueryOperations.OP_UPDATE) {
- // handle which types of parameters we are using, if any
- if (_positional != null)
- return asInt(_query.updateAll(_positional));
- if (_named != null)
- return asInt(_query.updateAll(_named));
- return asInt(_query.updateAll());
+ return asInt(_query.updateAll(_params));
}
throw new InvalidStateException(_loc.get("not-update-delete-query",
_query.getQueryString()), null, null, false);
@@ -510,6 +327,8 @@
if (value instanceof String)
value = Boolean.valueOf((String) value);
setSubclasses(((Boolean) value).booleanValue());
+ } else if ("InvalidateCache".equals(k)) {
+ invalidate();
} else if ("FilterListener".equals(k))
addFilterListener(Filters.hintToFilterListener(value, _query
.getBroker().getClassLoader()));
@@ -570,8 +389,8 @@
return setParameter(position, convertTemporalType(value, t));
}
- public OpenJPAQuery setParameter(int position, Date value, TemporalType type) {
- return setParameter(position, convertTemporalType(value, type));
+ public OpenJPAQuery setParameter(int pos, Date value, TemporalType type) {
+ return setParameter(pos, convertTemporalType(value, type));
}
/**
@@ -600,28 +419,10 @@
_em.assertNotCloseInvoked();
_query.lock();
try {
- if (isNative() && position < 1) {
- throw new IllegalArgumentException(_loc.get("bad-pos-params",
- position, _query.getQueryString()).toString());
- }
- // not allowed to mix positional and named parameters (EDR2 3.6.4)
- if (_named != null)
- throw new InvalidStateException(_loc.get(
- "no-pos-named-params-mix", _query.getQueryString()),
- null, null, false);
-
- if (position < 1)
- throw new InvalidStateException(_loc.get("illegal-index",
- position), null, null, false);
-
- if (_positional == null)
- _positional = new TreeMap<Integer, Object>();
-
- _positional.put(position, value);
- for (int i = 1; i < position; i++)
- if (!_positional.containsKey(i))
- _positional.put(i, GAP_FILLER);
-
+ if (_params == null)
+ _params = new ParameterMap(isNative() ?
+ ParameterMap.Type.POSITIONAL : null);
+ _params.put(position, value);
return this;
} finally {
_query.unlock();
@@ -633,8 +434,8 @@
return setParameter(name, convertTemporalType(value, type));
}
- public OpenJPAQuery setParameter(String name, Date value, TemporalType type) {
- return setParameter(name, convertTemporalType(value, type));
+ public OpenJPAQuery setParameter(String name, Date value, TemporalType t) {
+ return setParameter(name, convertTemporalType(value, t));
}
public OpenJPAQuery setParameter(String name, Object value) {
@@ -642,19 +443,10 @@
_em.assertNotCloseInvoked();
_query.lock();
try {
- if (isNative()) {
- throw new IllegalArgumentException(_loc.get("no-named-params",
- name, _query.getQueryString()).toString());
- }
- // not allowed to mix positional and named parameters (EDR2 3.6.4)
- if (_positional != null)
- throw new InvalidStateException(_loc.get(
- "no-pos-named-params-mix", _query.getQueryString()),
- null, null, false);
-
- if (_named == null)
- _named = new HashMap();
- _named.put(name, value);
+ if (_params == null)
+ _params = new ParameterMap(isNative() ?
+ ParameterMap.Type.POSITIONAL : null);
+ _params.put(name, value);
return this;
} finally {
_query.unlock();
@@ -664,37 +456,30 @@
public boolean isNative() {
return QueryLanguages.LANG_SQL.equals(getLanguage());
}
-
+
public boolean hasPositionalParameters() {
- return _positional != null;
+ return _params != null && _params.isPositional() && !_params.isEmpty();
}
- /**
- * Gets the array of positional parameter values. A value of
- * <code>GAP_FILLER</code> indicates that user has not set the
- * corresponding positional parameter. A value of null implies that user has
- * set the value as null.
- */
public Object[] getPositionalParameters() {
_query.lock();
try {
- return (_positional == null) ? EMPTY_ARRAY : _positional.values()
- .toArray();
+ return hasPositionalParameters() ? _params.values().toArray()
+ : EMPTY_ARRAY;
} finally {
_query.unlock();
}
}
-
+
public OpenJPAQuery setParameters(Object... params) {
_query.assertOpen();
_em.assertNotCloseInvoked();
_query.lock();
try {
- _positional = null;
- _named = null;
- if (params != null)
- for (int i = 0; i < params.length; i++)
- setParameter(i + 1, params[i]);
+ if (params == null)
+ return this;
+ for (int i = 0; i < params.length; i++)
+ setParameter(i + 1, params[i]);
return this;
} finally {
_query.unlock();
@@ -704,8 +489,8 @@
public Map getNamedParameters() {
_query.lock();
try {
- return (_named == null) ? Collections.EMPTY_MAP : Collections
- .unmodifiableMap(_named);
+ return (_params == null || !_params.isNamed())
+ ? Collections.EMPTY_MAP : _params.getMap();
} finally {
_query.unlock();
}
@@ -716,11 +501,12 @@
_em.assertNotCloseInvoked();
_query.lock();
try {
- _positional = null;
- _named = null;
- if (params != null)
- for (Map.Entry e : (Set<Map.Entry>) params.entrySet())
- setParameter((String) e.getKey(), e.getValue());
+ if (params == null)
+ return this;
+ if (_params == null)
+ _params = new ParameterMap(isNative() ?
+ ParameterMap.Type.POSITIONAL : null);
+ _params.putAll(params);
return this;
} finally {
_query.unlock();
@@ -735,6 +521,77 @@
public String[] getDataStoreActions(Map params) {
return _query.getDataStoreActions(params);
}
+
+ QueryImpl setId(String id) {
+ _id = id;
+ return this;
+ }
+
+ /**
+ * Validates internal parameters against a given expected parameter types.
+ *
+ * @param expected contains expected types of parameters.
+ * @param strict if true then also enforces that the parameter keys match.
+ * Otherwise only the types are compared.
+ * A more lenient strategy is required to accommodate the use case where
+ * named parameters are set on a JPQL query but the query is executed
+ * directly as a cached SQL which only supports positional parameters.
+ */
+ void validate(LinkedMap expected, boolean strict) {
+ if (_params == null) {
+ if (expected != null && !expected.isEmpty())
+ throw new UserException(_loc.get("param-unset", expected));
+ } else {
+ _params.validate(expected, strict);
+ }
+ }
+
+ /**
+ * Gets the values from ParameterMap as a map with deterministic iteration
+ * order, optionally converting a named map to a positional one.
+ */
+ Map getParameterMap(boolean convertToPositional) {
+ if (_params == null)
+ return null;
+ if (convertToPositional && !_params.isPositional())
+ return _params.toPositional().getMap();
+ return _params.getMap();
+ }
+
+ /**
+ * Cache this query with its identifier as key and SQL as value if this
+ * query is amenable to caching and has not already been cached.
+ *
+ * @return non-null if this query has already been cached. null if it can
+ * not be cached or cached in this call.
+ */
+ PreparedQuery cache() {
+ if (_id == null)
+ return null;
+ Map cache = _em.getConfiguration().getPreparedQueryCacheInstance();
+ if (cache == null)
+ return null;
+ PreparedQuery cached = (PreparedQuery)cache.get(_id);
+ if (cached == PreparedQuery.NOT_CACHABLE)
+ return null;
+ if (cached == null) {
+ String[] sqls = _query.getDataStoreActions(getParameterMap(true));
+ boolean cacheable = sqls.length == 1;
+ if (!cacheable) {
+ cache.put(_id, PreparedQuery.NOT_CACHABLE);
+ return null;
+ }
+ cached = new PreparedQuery(_id, sqls[0], _query);
+ cache.put(_id, cached);
+ return null;
+ }
+ return cached;
+ }
+
+ public boolean invalidate() {
+ Map cache = _em.getConfiguration().getPreparedQueryCacheInstance();
+ return cache != null && cache.remove(_id) != null;
+ }
public int hashCode() {
return _query.hashCode();