Home » apache-openjpa-1.1.0-source » org.apache.openjpa.jdbc » kernel » [javadoc | source]
    1   /*
    2    * Licensed to the Apache Software Foundation (ASF) under one
    3    * or more contributor license agreements.  See the NOTICE file
    4    * distributed with this work for additional information
    5    * regarding copyright ownership.  The ASF licenses this file
    6    * to you under the Apache License, Version 2.0 (the
    7    * "License"); you may not use this file except in compliance
    8    * with the License.  You may obtain a copy of the License at
    9    *
   10    * http://www.apache.org/licenses/LICENSE-2.0
   11    *
   12    * Unless required by applicable law or agreed to in writing,
   13    * software distributed under the License is distributed on an
   14    * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
   15    * KIND, either express or implied.  See the License for the
   16    * specific language governing permissions and limitations
   17    * under the License.    
   18    */
   19   package org.apache.openjpa.jdbc.kernel;
   20   
   21   import java.sql.Connection;
   22   import java.sql.SQLException;
   23   import javax.sql.DataSource;
   24   import javax.transaction.Transaction;
   25   import javax.transaction.TransactionManager;
   26   
   27   import org.apache.openjpa.jdbc.conf.JDBCConfiguration;
   28   import org.apache.openjpa.jdbc.meta.ClassMapping;
   29   import org.apache.openjpa.jdbc.schema.SchemaGroup;
   30   import org.apache.openjpa.jdbc.sql.SQLExceptions;
   31   import org.apache.openjpa.kernel.StoreContext;
   32   import org.apache.openjpa.meta.ClassMetaData;
   33   import org.apache.openjpa.util.OpenJPAException;
   34   import org.apache.openjpa.util.StoreException;
   35   
   36   /**
   37    * Abstract sequence implementation. Handles obtaining the proper
   38    * connection to used based on whether the sequence is transactional and
   39    * whether a second datasource is configured.
   40    *
   41    * @author Abe White
   42    */
   43   public abstract class AbstractJDBCSeq
   44       implements JDBCSeq {
   45   
   46       protected int type = TYPE_DEFAULT;
   47       protected Object current = null;
   48       private static ThreadLocal _outerTransaction = new ThreadLocal();
   49   
   50       /**
   51        * Records the sequence type.
   52        */
   53       public void setType(int type) {
   54           this.type = type;
   55       }
   56   
   57       public Object next(StoreContext ctx, ClassMetaData meta) {
   58           JDBCStore store = getStore(ctx);
   59           try {
   60               current = nextInternal(store, (ClassMapping) meta);
   61               return current;
   62           } catch (OpenJPAException ke) {
   63               throw ke;
   64           } catch (SQLException se) {
   65               throw SQLExceptions.getStore(se, store.getDBDictionary());
   66           } catch (Exception e) {
   67               throw new StoreException(e);
   68           }
   69       }
   70   
   71       public Object current(StoreContext ctx, ClassMetaData meta) {
   72           JDBCStore store = getStore(ctx);
   73           try {
   74               return currentInternal(store, (ClassMapping) meta);
   75           } catch (OpenJPAException ke) {
   76               throw ke;
   77           } catch (SQLException se) {
   78               throw SQLExceptions.getStore(se, store.getDBDictionary());
   79           } catch (Exception e) {
   80               throw new StoreException(e);
   81           }
   82       }
   83   
   84       public void allocate(int additional, StoreContext ctx, ClassMetaData meta) {
   85           JDBCStore store = getStore(ctx);
   86           try {
   87               allocateInternal(additional, store, (ClassMapping) meta);
   88           } catch (OpenJPAException ke) {
   89               throw ke;
   90           } catch (SQLException se) {
   91               throw SQLExceptions.getStore(se, store.getDBDictionary());
   92           } catch (Exception e) {
   93               throw new StoreException(e);
   94           }
   95       }
   96   
   97       /**
   98        * No-op.
   99        */
  100       public void addSchema(ClassMapping mapping, SchemaGroup group) {
  101       }
  102   
  103       /**
  104        * No-op.
  105        */
  106       public void close() {
  107       }
  108   
  109       /**
  110        * Return the next sequence object.
  111        */
  112       protected abstract Object nextInternal(JDBCStore store,
  113           ClassMapping mapping)
  114           throws Exception;
  115       
  116       /**
  117        * Return the {@link JDBCConfiguration} for this sequence.
  118        */
  119       public abstract JDBCConfiguration getConfiguration();
  120   
  121       /**
  122        * Return the current sequence object. By default returns the last
  123        * sequence value used, or null if no sequence values have been requested
  124        * yet. Default implementation is not threadsafe.
  125        */
  126       protected Object currentInternal(JDBCStore store, ClassMapping mapping)
  127           throws Exception {
  128           return current;
  129       }
  130   
  131       /**
  132        * Allocate additional sequence values. Does nothing by default.
  133        */
  134       protected void allocateInternal(int additional, JDBCStore store,
  135           ClassMapping mapping)
  136           throws Exception {
  137       }
  138   
  139       /**
  140        * Extract the store from the given context.
  141        */
  142       private JDBCStore getStore(StoreContext ctx) {
  143           return (JDBCStore) ctx.getStoreManager().getInnermostDelegate();
  144       }
  145   
  146       /**
  147        * Return the connection to use based on the type of sequence. This
  148        * connection will automatically be closed; do not close it.
  149        */
  150       protected Connection getConnection(JDBCStore store)
  151           throws SQLException {
  152           if (type == TYPE_TRANSACTIONAL || type == TYPE_CONTIGUOUS)
  153               return store.getConnection();
  154           else if (suspendInJTA()) {
  155               try {
  156                   TransactionManager tm = getConfiguration()
  157                       .getManagedRuntimeInstance().getTransactionManager();
  158                   _outerTransaction.set(tm.suspend());
  159                   tm.begin();
  160                   return store.getConnection();
  161               } catch (Exception e) {
  162                   throw new StoreException(e);
  163               }
  164           } else {
  165               JDBCConfiguration conf = store.getConfiguration();
  166               DataSource ds = conf.getDataSource2(store.getContext());
  167               Connection conn = ds.getConnection();
  168               if (conn.getAutoCommit())
  169                   conn.setAutoCommit(false);
  170               return conn;
  171           }
  172       }
  173   
  174       /**
  175        * Close the current connection.
  176        */
  177       protected void closeConnection(Connection conn) {
  178           if (conn == null)
  179               return;
  180   
  181           if (type == TYPE_TRANSACTIONAL || type == TYPE_CONTIGUOUS) {
  182               // do nothing; this seq is part of the business transaction
  183               return;
  184           } else if (suspendInJTA()) {
  185               try {
  186                   TransactionManager tm = getConfiguration()
  187                       .getManagedRuntimeInstance().getTransactionManager();
  188                   tm.commit();
  189                   try { conn.close(); } catch (SQLException se) {}
  190   
  191                   Transaction outerTxn = (Transaction)_outerTransaction.get();
  192                   if (outerTxn != null)
  193                       tm.resume(outerTxn);
  194   
  195               } catch (Exception e) {
  196                   throw new StoreException(e);
  197               } finally {
  198                   _outerTransaction.set(null);
  199               }
  200           } else {
  201               try {
  202                   conn.commit();
  203               } catch (SQLException se) {
  204                   throw SQLExceptions.getStore(se);
  205               } finally {
  206                   try { conn.close(); } catch (SQLException se) {}
  207               }
  208           }
  209       }
  210       
  211       /**
  212        * Detect whether or not OpenJPA should suspend the transaction in 
  213        * a managed environment.
  214        */
  215       protected boolean suspendInJTA() {
  216           return getConfiguration().isConnectionFactoryModeManaged() && 
  217               getConfiguration().getConnectionFactory2() == null;
  218       }
  219   }

Save This Page
Home » apache-openjpa-1.1.0-source » org.apache.openjpa.jdbc » kernel » [javadoc | source]