You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@openjpa.apache.org by pc...@apache.org on 2007/04/07 01:22:08 UTC

svn commit: r526316 - in /incubator/openjpa/trunk: openjpa-jdbc/src/main/java/org/apache/openjpa/jdbc/sql/ openjpa-persistence-jdbc/src/main/java/org/apache/openjpa/persistence/jdbc/ openjpa-persistence-jdbc/src/test/java/org/apache/openjpa/persistence...

Author: pcl
Date: Fri Apr  6 16:22:06 2007
New Revision: 526316

URL: http://svn.apache.org/viewvc?view=rev&rev=526316
Log:
OPENJPA-182. Changed JDBCFetchPlan.setIsolation() to use enums; added logic to handle enum hints to QueryImpl; moved from IllegalArgumentException to InvalidArgumentException to unify exception processing for both queries and find calls.

Added:
    incubator/openjpa/trunk/openjpa-persistence-jdbc/src/main/java/org/apache/openjpa/persistence/jdbc/IsolationLevel.java   (with props)
Modified:
    incubator/openjpa/trunk/openjpa-jdbc/src/main/java/org/apache/openjpa/jdbc/sql/DBDictionary.java
    incubator/openjpa/trunk/openjpa-persistence-jdbc/src/main/java/org/apache/openjpa/persistence/jdbc/JDBCFetchPlan.java
    incubator/openjpa/trunk/openjpa-persistence-jdbc/src/main/java/org/apache/openjpa/persistence/jdbc/JDBCFetchPlanImpl.java
    incubator/openjpa/trunk/openjpa-persistence-jdbc/src/test/java/org/apache/openjpa/persistence/jdbc/TestIsolationLevelOverride.java
    incubator/openjpa/trunk/openjpa-persistence/src/main/java/org/apache/openjpa/persistence/QueryImpl.java

Modified: incubator/openjpa/trunk/openjpa-jdbc/src/main/java/org/apache/openjpa/jdbc/sql/DBDictionary.java
URL: http://svn.apache.org/viewvc/incubator/openjpa/trunk/openjpa-jdbc/src/main/java/org/apache/openjpa/jdbc/sql/DBDictionary.java?view=diff&rev=526316&r1=526315&r2=526316
==============================================================================
--- incubator/openjpa/trunk/openjpa-jdbc/src/main/java/org/apache/openjpa/jdbc/sql/DBDictionary.java (original)
+++ incubator/openjpa/trunk/openjpa-jdbc/src/main/java/org/apache/openjpa/jdbc/sql/DBDictionary.java Fri Apr  6 16:22:06 2007
@@ -96,6 +96,7 @@
 import org.apache.openjpa.util.StoreException;
 import org.apache.openjpa.util.UnsupportedException;
 import org.apache.openjpa.util.UserException;
+import org.apache.openjpa.util.InvalidStateException;
 import serp.util.Numbers;
 import serp.util.Strings;
 
@@ -2156,9 +2157,8 @@
     protected String getForUpdateClause(JDBCFetchConfiguration fetch,
         boolean forUpdate) {
         if (fetch != null && fetch.getIsolation() != -1) {
-            throw new IllegalStateException(_loc.get(
-                "isolation-level-config-not-supported", getClass().getName())
-                .getMessage());
+            throw new InvalidStateException(_loc.get(
+                "isolation-level-config-not-supported", getClass().getName()));
         } else if (forUpdate && !simulateLocking) {
             assertSupport(supportsSelectForUpdate, "SupportsSelectForUpdate");
             return forUpdateClause;

Added: incubator/openjpa/trunk/openjpa-persistence-jdbc/src/main/java/org/apache/openjpa/persistence/jdbc/IsolationLevel.java
URL: http://svn.apache.org/viewvc/incubator/openjpa/trunk/openjpa-persistence-jdbc/src/main/java/org/apache/openjpa/persistence/jdbc/IsolationLevel.java?view=auto&rev=526316
==============================================================================
--- incubator/openjpa/trunk/openjpa-persistence-jdbc/src/main/java/org/apache/openjpa/persistence/jdbc/IsolationLevel.java (added)
+++ incubator/openjpa/trunk/openjpa-persistence-jdbc/src/main/java/org/apache/openjpa/persistence/jdbc/IsolationLevel.java Fri Apr  6 16:22:06 2007
@@ -0,0 +1,71 @@
+/*
+ * Copyright 2006 The Apache Software Foundation.
+ *
+ * Licensed 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.jdbc;
+
+import java.sql.Connection;
+
+import org.apache.openjpa.jdbc.kernel.JDBCFetchConfiguration;
+
+/**
+ * Isolation levels for use in {@link JDBCFetchPlan#setIsolation}.
+ *
+ * @since 0.9.7
+ */
+public enum IsolationLevel {
+    DEFAULT(-1),
+    NONE(Connection.TRANSACTION_NONE),
+    READ_UNCOMMITTED(Connection.TRANSACTION_READ_UNCOMMITTED),
+    READ_COMMITTED(Connection.TRANSACTION_READ_COMMITTED),
+    REPEATABLE_READ(Connection.TRANSACTION_REPEATABLE_READ),
+    SERIALIZABLE(Connection.TRANSACTION_SERIALIZABLE);
+
+    private final int _connectionConstant;
+
+    private IsolationLevel(int connectionConstant) {
+        _connectionConstant = connectionConstant;
+    }
+
+    protected int getConnectionConstant() {
+        return _connectionConstant;
+    }
+
+    protected static IsolationLevel fromConnectionConstant(int constant) {
+        switch(constant) {
+            case -1:
+            case JDBCFetchConfiguration.DEFAULT:
+                return DEFAULT;
+
+            case Connection.TRANSACTION_NONE:
+                return NONE;
+
+            case Connection.TRANSACTION_READ_UNCOMMITTED:
+                return READ_UNCOMMITTED;
+
+            case Connection.TRANSACTION_READ_COMMITTED:
+                return READ_COMMITTED;
+
+            case Connection.TRANSACTION_REPEATABLE_READ:
+                return REPEATABLE_READ;
+
+            case Connection.TRANSACTION_SERIALIZABLE:
+                return SERIALIZABLE;
+
+            default:
+                throw new IllegalArgumentException(
+                    Integer.valueOf(constant).toString());
+        }
+    }
+}

Propchange: incubator/openjpa/trunk/openjpa-persistence-jdbc/src/main/java/org/apache/openjpa/persistence/jdbc/IsolationLevel.java
------------------------------------------------------------------------------
    svn:eol-style = native

Modified: incubator/openjpa/trunk/openjpa-persistence-jdbc/src/main/java/org/apache/openjpa/persistence/jdbc/JDBCFetchPlan.java
URL: http://svn.apache.org/viewvc/incubator/openjpa/trunk/openjpa-persistence-jdbc/src/main/java/org/apache/openjpa/persistence/jdbc/JDBCFetchPlan.java?view=diff&rev=526316&r1=526315&r2=526316
==============================================================================
--- incubator/openjpa/trunk/openjpa-persistence-jdbc/src/main/java/org/apache/openjpa/persistence/jdbc/JDBCFetchPlan.java (original)
+++ incubator/openjpa/trunk/openjpa-persistence-jdbc/src/main/java/org/apache/openjpa/persistence/jdbc/JDBCFetchPlan.java Fri Apr  6 16:22:06 2007
@@ -15,8 +15,6 @@
  */
 package org.apache.openjpa.persistence.jdbc;
 
-import java.sql.Connection;
-
 import org.apache.openjpa.jdbc.kernel.EagerFetchModes;
 import org.apache.openjpa.jdbc.kernel.LRSSizes;
 import org.apache.openjpa.jdbc.sql.JoinSyntaxes;
@@ -118,36 +116,20 @@
     public JDBCFetchPlan setJoinSyntax(int syntax);
 
     /**
-     * <p>The isolation level for queries issued to the database. This overrides
+     * The isolation level for queries issued to the database. This overrides
      * the persistence-unit-wide <code>openjpa.jdbc.TransactionIsolation</code>
-     * value.</p>
-     *
-     * <p>Must be one of {@link Connection#TRANSACTION_NONE},
-     * {@link Connection#TRANSACTION_READ_UNCOMMITTED},
-     * {@link Connection#TRANSACTION_READ_COMMITTED},
-     * {@link Connection#TRANSACTION_REPEATABLE_READ}, 
-     * {@link Connection#TRANSACTION_SERIALIZABLE},
-     * or -1 for the default connection level specified by the context in
-     * which this fetch plan is being used.</p>
+     * value.
      *
      * @since 0.9.7
      */
-    public int getIsolation();
+    public IsolationLevel getIsolation();
 
     /**
-     * <p>The isolation level for queries issued to the database. This overrides
+     * The isolation level for queries issued to the database. This overrides
      * the persistence-unit-wide <code>openjpa.jdbc.TransactionIsolation</code>
-     * value.</p>
-     *
-     * <p>Must be one of {@link Connection#TRANSACTION_NONE},
-     * {@link Connection#TRANSACTION_READ_UNCOMMITTED},
-     * {@link Connection#TRANSACTION_READ_COMMITTED},
-     * {@link Connection#TRANSACTION_REPEATABLE_READ},
-     * {@link Connection#TRANSACTION_SERIALIZABLE},
-     * or -1 for the default connection level specified by the context in
-     * which this fetch plan is being used.</p>
+     * value.
      *
      * @since 0.9.7
      */
-    public JDBCFetchPlan setIsolation(int level);
+    public JDBCFetchPlan setIsolation(IsolationLevel level);
 }

Modified: incubator/openjpa/trunk/openjpa-persistence-jdbc/src/main/java/org/apache/openjpa/persistence/jdbc/JDBCFetchPlanImpl.java
URL: http://svn.apache.org/viewvc/incubator/openjpa/trunk/openjpa-persistence-jdbc/src/main/java/org/apache/openjpa/persistence/jdbc/JDBCFetchPlanImpl.java?view=diff&rev=526316&r1=526315&r2=526316
==============================================================================
--- incubator/openjpa/trunk/openjpa-persistence-jdbc/src/main/java/org/apache/openjpa/persistence/jdbc/JDBCFetchPlanImpl.java (original)
+++ incubator/openjpa/trunk/openjpa-persistence-jdbc/src/main/java/org/apache/openjpa/persistence/jdbc/JDBCFetchPlanImpl.java Fri Apr  6 16:22:06 2007
@@ -103,12 +103,12 @@
         return this;
     }
 
-    public int getIsolation() {
-        return _fetch.getIsolation();
+    public IsolationLevel getIsolation() {
+        return IsolationLevel.fromConnectionConstant(_fetch.getIsolation());
     }
 
-    public JDBCFetchPlan setIsolation(int level) {
-        _fetch.setIsolation(level);
+    public JDBCFetchPlan setIsolation(IsolationLevel level) {
+        _fetch.setIsolation(level.getConnectionConstant());
         return this;
     }
 }

Modified: incubator/openjpa/trunk/openjpa-persistence-jdbc/src/test/java/org/apache/openjpa/persistence/jdbc/TestIsolationLevelOverride.java
URL: http://svn.apache.org/viewvc/incubator/openjpa/trunk/openjpa-persistence-jdbc/src/test/java/org/apache/openjpa/persistence/jdbc/TestIsolationLevelOverride.java?view=diff&rev=526316&r1=526315&r2=526316
==============================================================================
--- incubator/openjpa/trunk/openjpa-persistence-jdbc/src/test/java/org/apache/openjpa/persistence/jdbc/TestIsolationLevelOverride.java (original)
+++ incubator/openjpa/trunk/openjpa-persistence-jdbc/src/test/java/org/apache/openjpa/persistence/jdbc/TestIsolationLevelOverride.java Fri Apr  6 16:22:06 2007
@@ -15,13 +15,14 @@
  */
 package org.apache.openjpa.persistence.jdbc;
 
-import java.sql.Connection;
-import javax.persistence.PersistenceException;
+import javax.persistence.Query;
 
 import org.apache.openjpa.persistence.test.SQLListenerTestCase;
 import org.apache.openjpa.persistence.simple.AllFieldTypes;
 import org.apache.openjpa.persistence.OpenJPAPersistence;
 import org.apache.openjpa.persistence.OpenJPAEntityManager;
+import org.apache.openjpa.persistence.OpenJPAQuery;
+import org.apache.openjpa.persistence.InvalidStateException;
 import org.apache.openjpa.jdbc.sql.DBDictionary;
 import org.apache.openjpa.jdbc.sql.DB2Dictionary;
 import org.apache.openjpa.jdbc.sql.HSQLDictionary;
@@ -36,7 +37,20 @@
             "openjpa.LockManager", "pessimistic");
     }
 
-    public void testIsolationLevelOverride() {
+    public void testIsolationOverrideViaFetchPlan() {
+        testIsolationLevelOverride(false, false);
+    }
+
+    public void testIsolationOverrideViaHint() {
+        testIsolationLevelOverride(true, false);
+    }
+
+    public void testIsolationOverrideViaStringHint() {
+        testIsolationLevelOverride(true, true);
+    }
+
+    public void testIsolationLevelOverride(boolean useHintsAndQueries,
+        boolean useStringHints) {
         OpenJPAEntityManager em =
             OpenJPAPersistence.cast(emf.createEntityManager());
         DBDictionary dict = ((JDBCConfiguration) em.getConfiguration())
@@ -49,9 +63,27 @@
         sql.clear();
         try {
             em.getTransaction().begin();
-            ((JDBCFetchPlan) em.getFetchPlan())
-                .setIsolation(Connection.TRANSACTION_SERIALIZABLE);
-            em.find(AllFieldTypes.class, 0);
+            if (useHintsAndQueries) {
+                Query q = em.createQuery(
+                    "select o from AllFieldTypes o where o.intField = :p");
+                q.setParameter("p", 0);
+                if (useStringHints) {
+                    q.setHint("openjpa.FetchPlan.Isolation", "SERIALIZABLE");
+                } else {
+                    q.setHint("openjpa.FetchPlan.Isolation",
+                        IsolationLevel.SERIALIZABLE);
+                }
+
+                assertEquals(IsolationLevel.SERIALIZABLE,
+                    ((JDBCFetchPlan) ((OpenJPAQuery) q).getFetchPlan())
+                        .getIsolation());
+
+                q.getResultList();
+            } else {
+                ((JDBCFetchPlan) em.getFetchPlan())
+                    .setIsolation(IsolationLevel.SERIALIZABLE);
+                em.find(AllFieldTypes.class, 0);
+            }
 
             if (dict instanceof DB2Dictionary) {
                 assertEquals(1, sql.size());
@@ -60,10 +92,9 @@
                 fail("OpenJPA currently only supports per-query isolation " +
                     "level configuration on the following databases: DB2");
             }
-        } catch (PersistenceException pe) {
-            // if we're not using DB2, we expect an IllegalStateException.
-            if (dict instanceof DB2Dictionary
-                || !(pe.getCause() instanceof IllegalStateException))
+        } catch (InvalidStateException pe) {
+            // if we're not using DB2, we expect an InvalidStateException.
+            if (dict instanceof DB2Dictionary)
                 throw pe;
         } finally {
             em.getTransaction().rollback();

Modified: incubator/openjpa/trunk/openjpa-persistence/src/main/java/org/apache/openjpa/persistence/QueryImpl.java
URL: http://svn.apache.org/viewvc/incubator/openjpa/trunk/openjpa-persistence/src/main/java/org/apache/openjpa/persistence/QueryImpl.java?view=diff&rev=526316&r1=526315&r2=526316
==============================================================================
--- incubator/openjpa/trunk/openjpa-persistence/src/main/java/org/apache/openjpa/persistence/QueryImpl.java (original)
+++ incubator/openjpa/trunk/openjpa-persistence/src/main/java/org/apache/openjpa/persistence/QueryImpl.java Fri Apr  6 16:22:06 2007
@@ -26,6 +26,7 @@
 import java.util.List;
 import java.util.Map;
 import java.util.Set;
+import java.lang.reflect.Method;
 import javax.persistence.FlushModeType;
 import javax.persistence.Query;
 import javax.persistence.TemporalType;
@@ -38,6 +39,7 @@
 import org.apache.openjpa.kernel.exps.FilterListener;
 import org.apache.openjpa.lib.rop.ResultList;
 import org.apache.openjpa.lib.util.Localizer;
+import org.apache.openjpa.enhance.Reflection;
 
 /**
  * Implementation of {@link Query} interface.
@@ -364,7 +366,7 @@
                     addAggregateListener(arr[i]);
             } else if (k.startsWith("FetchPlan.")) {
                 k = k.substring("FetchPlan.".length());
-                Filters.hintToSetter(getFetchPlan(), k, value);
+                hintToSetter(getFetchPlan(), k, value);
             } else if (k.startsWith("hint.")) {
                 if ("hint.OptimizeResultCount".equals(k)) {
                     if (value instanceof String) {
@@ -388,6 +390,18 @@
         } catch (Exception e) {
             throw PersistenceExceptions.toPersistenceException(e);
         }
+    }
+
+    private void hintToSetter(FetchPlan fetchPlan, String k, Object value) {
+        if (fetchPlan == null || k == null)
+            return;
+
+        Method setter = Reflection.findSetter(fetchPlan.getClass(), k, true);
+        Class paramType = setter.getParameterTypes()[0];
+        if (Enum.class.isAssignableFrom(paramType) && value instanceof String)
+            value = Enum.valueOf(paramType, (String) value);
+        
+        Filters.hintToSetter(fetchPlan, k, value);
     }
 
     public OpenJPAQuery setParameter(int position, Calendar value,