db-ojb-dev mailing list archives

Site index · List index
Message view « Date » · « Thread »
Top « Date » · « Thread »
From olegn...@apache.org
Subject cvs commit: jakarta-ojb/src/java/org/apache/ojb/broker/util/batch BatchConnection.java BatchPreparedStatement.java PreparedStatementInvocationHandler.java
Date Mon, 02 Dec 2002 17:14:13 GMT
olegnitz    2002/12/02 09:14:13

  Added:       src/java/org/apache/ojb/broker/util/batch
                        BatchConnection.java BatchPreparedStatement.java
                        PreparedStatementInvocationHandler.java
  Log:
  ConnectionManager now has the batch mode - all PreparedStatements with
  the same SQL string are authomatically gathered into batches.
  
  Revision  Changes    Path
  1.1                  jakarta-ojb/src/java/org/apache/ojb/broker/util/batch/BatchConnection.java
  
  Index: BatchConnection.java
  ===================================================================
  package org.apache.ojb.broker.util.batch;
  
  /* ====================================================================
   * The Apache Software License, Version 1.1
   *
   * Copyright (c) 2001 The Apache Software Foundation.  All rights
   * reserved.
   *
   * Redistribution and use in source and binary forms, with or without
   * modification, are permitted provided that the following conditions
   * are met:
   *
   * 1. Redistributions of source code must retain the above copyright
   *    notice, this list of conditions and the following disclaimer.
   *
   * 2. Redistributions in binary form must reproduce the above copyright
   *    notice, this list of conditions and the following disclaimer in
   *    the documentation and/or other materials provided with the
   *    distribution.
   *
   * 3. The end-user documentation included with the redistribution,
   *    if any, must include the following acknowledgment:
   *       "This product includes software developed by the
   *        Apache Software Foundation (http://www.apache.org/)."
   *    Alternately, this acknowledgment may appear in the software itself,
   *    if and wherever such third-party acknowledgments normally appear.
   *
   * 4. The names "Apache" and "Apache Software Foundation" and
   *    "Apache ObjectRelationalBridge" must not be used to endorse or promote products
   *    derived from this software without prior written permission. For
   *    written permission, please contact apache@apache.org.
   *
   * 5. Products derived from this software may not be called "Apache",
   *    "Apache ObjectRelationalBridge", nor may "Apache" appear in their name, without
   *    prior written permission of the Apache Software Foundation.
   *
   * THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESSED OR IMPLIED
   * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
   * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
   * DISCLAIMED.  IN NO EVENT SHALL THE APACHE SOFTWARE FOUNDATION OR
   * ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
   * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
   * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF
   * USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
   * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
   * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT
   * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
   * SUCH DAMAGE.
   * ====================================================================
   *
   * This software consists of voluntary contributions made by many
   * individuals on behalf of the Apache Software Foundation.  For more
   * information on the Apache Software Foundation, please see
   * <http://www.apache.org/>.
   */
  
  
  import java.sql.CallableStatement;
  import java.sql.Connection;
  import java.sql.DatabaseMetaData;
  import java.sql.PreparedStatement;
  import java.sql.SQLException;
  import java.sql.SQLWarning;
  import java.sql.Statement;
  import java.util.ArrayList;
  import java.util.HashMap;
  import java.util.Iterator;
  import java.util.Map;
  
  //#ifdef JDK13
  import java.lang.reflect.Proxy;
  //#else
  /*
  import com.develop.java.lang.reflect.Proxy;
  */
  //#endif
  
  /**
   * The implementation of {@link java.sql.Connection} which
   * automatically gathers INSERT, UPDATE and DELETE
   * PreparedStatements into batches.
   *
   * @author Oleg Nitz (<a href="mailto:olegnitz@apache.org">olegnitz@apache.org</a>)
   */
  public class BatchConnection implements Connection
  {
      private Connection _conn;
      
      private boolean _useBatchInserts;
  
      private HashMap _statements = new HashMap();
  
      private ArrayList _order = new ArrayList();
  
      public BatchConnection(Connection conn)
      {
          _conn = conn;
      }
  
      public void setUseBatchInserts(boolean useBatchInserts)
      {
          _useBatchInserts = useBatchInserts;
      }
  
      /**
       * Get the original Connection
       */
      public Connection getOriginalConnection()
      {
          return _conn;
      }
  
      /**
       * Remember the order of execution
       */
      void nextExecuted(String sql)
      {
          if (!_order.contains(sql))
          {
              _order.add(sql);
          }
          else if (sql.substring(0, 7).toUpperCase().equals("DELETE "));
          {
              // Put deletion of master objects after all dependent objects
              _order.remove(sql);
              _order.add(sql);
          }
      }
  
      /**
       * If UPDATE, INSERT or DELETE, return BatchPreparedStatement,
       * otherwise return null.
       */
      private PreparedStatement prepareBatchStatement(String sql)
      {
          String sqlCmd = sql.substring(0, 7).toUpperCase();
  
          if (sqlCmd.equals("UPDATE ") || sqlCmd.equals("DELETE ")
                  || (_useBatchInserts && sqlCmd.equals("INSERT ")))
          {
              PreparedStatement stmt = (PreparedStatement) _statements.get(sql);
              if (stmt == null)
              {
                  stmt = (PreparedStatement) Proxy.newProxyInstance(getClass().getClassLoader(),
                              new Class[] {PreparedStatement.class, BatchPreparedStatement.class},
                              new PreparedStatementInvocationHandler(this, sql));
                  _statements.put(sql, stmt);
              }
              return stmt;
          }
          else
          {
              return null;
          }
      }
  
      public PreparedStatement prepareStatement(String sql)
              throws SQLException
      {
          PreparedStatement stmt = prepareBatchStatement(sql);
  
          if (stmt == null)
          {
              stmt = _conn.prepareStatement(sql);
          }
          return stmt;
      }
  
      public PreparedStatement prepareStatement(String sql,
                                                int resultSetType,
                                                int resultSetConcurrency)
              throws SQLException
      {
          PreparedStatement stmt = prepareBatchStatement(sql);
  
          if (stmt == null)
          {
              stmt = _conn.prepareStatement(sql, resultSetType, resultSetConcurrency);
          }
          return stmt;
      }
  
      public void executeBatch() throws SQLException
      {
          BatchPreparedStatement batchStmt;
          for (Iterator it = _order.iterator(); it.hasNext(); )
          {
              batchStmt = (BatchPreparedStatement) _statements.get(it.next());
              batchStmt.doExecute(_conn);
          }
          _order.clear();
          _statements.clear();
      }
  
      public void commit() throws SQLException
      {
          executeBatch();
          _conn.commit();
      }
  
      public void rollback() throws SQLException
      {
          _order.clear();
          _statements.clear();
          _conn.rollback();
      }
  
      public void close() throws SQLException
      {
          _conn.close();
      }
  
      public boolean isClosed() throws SQLException
      {
          return _conn.isClosed();
      }
  
      public Statement createStatement() throws SQLException
      {
          return _conn.createStatement();
      }
  
      public Statement createStatement(int resultSetType,
                                       int resultSetConcurrency)
              throws SQLException
      {
          return _conn.createStatement(resultSetType, resultSetConcurrency);
      }
  
      public CallableStatement prepareCall(String sql) throws SQLException
      {
          return _conn.prepareCall(sql);
      }
  
      public CallableStatement prepareCall(String sql,
                                           int resultSetType,
                                           int resultSetConcurrency)
              throws SQLException
      {
          return _conn.prepareCall(sql, resultSetType, resultSetConcurrency);
      }
  
      public void clearWarnings() throws SQLException
      {
          _conn.clearWarnings();
      }
  
      public boolean getAutoCommit() throws SQLException
      {
          return _conn.getAutoCommit();
      }
  
      public String getCatalog() throws SQLException
      {
          return _conn.getCatalog();
      }
  
      public DatabaseMetaData getMetaData() throws SQLException
      {
          return _conn.getMetaData();
      }
  
      public int getTransactionIsolation() throws SQLException
      {
          return _conn.getTransactionIsolation();
      }
  
      public Map getTypeMap() throws SQLException
      {
          return _conn.getTypeMap();
      }
  
      public SQLWarning getWarnings() throws SQLException
      {
          return _conn.getWarnings();
      }
  
      public boolean isReadOnly() throws SQLException
      {
          return _conn.isReadOnly();
      }
  
      public String nativeSQL(String sql) throws SQLException
      {
          return _conn.nativeSQL(sql);
      }
  
      public void setAutoCommit(boolean autoCommit) throws SQLException
      {
          _conn.setAutoCommit(autoCommit);
      }
  
      public void setCatalog(String catalog) throws SQLException
      {
          _conn.setCatalog(catalog);
      }
  
      public void setReadOnly(boolean readOnly) throws SQLException
      {
          _conn.setReadOnly(readOnly);
      }
  
      public void setTransactionIsolation(int level) throws SQLException
      {
          _conn.setTransactionIsolation(level);
      }
  
      public void setTypeMap(Map map) throws SQLException
      {
          _conn.setTypeMap(map);
      }
  
  
  
      // ------------------- JDBC 3.0 -----------------------------------------
      // Will be uncommented by the build process on a JDBC 3.0 system
  
  //#ifdef JDBC30
  
      public int getHoldability() throws SQLException {
          return _conn.getHoldability();
      }
  
      public void setHoldability(int holdability) throws SQLException {
          _conn.setHoldability(holdability);
      }
  
      public java.sql.Savepoint setSavepoint() throws SQLException {
          return _conn.setSavepoint();
      }
  
      public java.sql.Savepoint setSavepoint(String name) throws SQLException {
          return _conn.setSavepoint(name);
      }
  
      public void rollback(java.sql.Savepoint savepoint) throws SQLException {
          _conn.rollback(savepoint);
      }
  
      public void releaseSavepoint(java.sql.Savepoint savepoint) throws SQLException {
          _conn.releaseSavepoint(savepoint);
      }
  
      public Statement createStatement(int resultSetType,
                                       int resultSetConcurrency,
                                       int resultSetHoldability)
              throws SQLException {
          return _conn.createStatement(resultSetType, resultSetConcurrency,
                                       resultSetHoldability);
      }
  
      public PreparedStatement prepareStatement(String sql, int resultSetType,
                                                int resultSetConcurrency,
                                                int resultSetHoldability)
          throws SQLException {
          return _conn.prepareStatement(sql, resultSetType,
                                        resultSetConcurrency,
                                        resultSetHoldability);
      }
  
      public CallableStatement prepareCall(String sql, int resultSetType,
                                           int resultSetConcurrency,
                                           int resultSetHoldability)
              throws SQLException {
          return _conn.prepareCall(sql, resultSetType,
                                   resultSetConcurrency,
                                   resultSetHoldability);
      }
  
      public PreparedStatement prepareStatement(String sql, int autoGeneratedKeys)
              throws SQLException {
          return _conn.prepareStatement(sql, autoGeneratedKeys);
      }
  
      public PreparedStatement prepareStatement(String sql, int columnIndexes[])
              throws SQLException {
          return _conn.prepareStatement(sql, columnIndexes);
      }
  
      public PreparedStatement prepareStatement(String sql, String columnNames[])
              throws SQLException {
          return _conn.prepareStatement(sql, columnNames);
      }
  
  //#endif
  
  }
  
  
  
  1.1                  jakarta-ojb/src/java/org/apache/ojb/broker/util/batch/BatchPreparedStatement.java
  
  Index: BatchPreparedStatement.java
  ===================================================================
  package org.apache.ojb.broker.util.batch;
  
  /* ====================================================================
   * The Apache Software License, Version 1.1
   *
   * Copyright (c) 2001 The Apache Software Foundation.  All rights
   * reserved.
   *
   * Redistribution and use in source and binary forms, with or without
   * modification, are permitted provided that the following conditions
   * are met:
   *
   * 1. Redistributions of source code must retain the above copyright
   *    notice, this list of conditions and the following disclaimer.
   *
   * 2. Redistributions in binary form must reproduce the above copyright
   *    notice, this list of conditions and the following disclaimer in
   *    the documentation and/or other materials provided with the
   *    distribution.
   *
   * 3. The end-user documentation included with the redistribution,
   *    if any, must include the following acknowledgment:
   *       "This product includes software developed by the
   *        Apache Software Foundation (http://www.apache.org/)."
   *    Alternately, this acknowledgment may appear in the software itself,
   *    if and wherever such third-party acknowledgments normally appear.
   *
   * 4. The names "Apache" and "Apache Software Foundation" and
   *    "Apache ObjectRelationalBridge" must not be used to endorse or promote products
   *    derived from this software without prior written permission. For
   *    written permission, please contact apache@apache.org.
   *
   * 5. Products derived from this software may not be called "Apache",
   *    "Apache ObjectRelationalBridge", nor may "Apache" appear in their name, without
   *    prior written permission of the Apache Software Foundation.
   *
   * THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESSED OR IMPLIED
   * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
   * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
   * DISCLAIMED.  IN NO EVENT SHALL THE APACHE SOFTWARE FOUNDATION OR
   * ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
   * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
   * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF
   * USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
   * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
   * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT
   * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
   * SUCH DAMAGE.
   * ====================================================================
   *
   * This software consists of voluntary contributions made by many
   * individuals on behalf of the Apache Software Foundation.  For more
   * information on the Apache Software Foundation, please see
   * <http://www.apache.org/>.
   */
  
  
  import java.sql.Connection;
  import java.sql.SQLException;
  
  /**
   * The interface which is used to create dynamic proxy which will also
   * implement {@link java.sql.PreparedStatement} and allow to automatically gathers 
   * INSERT, UPDATE and DELETE PreparedStatements into batches.
   *
   * @author Oleg Nitz (<a href="mailto:olegnitz@apache.org">olegnitz@apache.org</a>)
   */
  public interface BatchPreparedStatement
  {
  
      /**
       * This method performs database modification at the very and of transaction.
       */
      public void doExecute(Connection conn) throws SQLException;
  }
  
  
  
  1.1                  jakarta-ojb/src/java/org/apache/ojb/broker/util/batch/PreparedStatementInvocationHandler.java
  
  Index: PreparedStatementInvocationHandler.java
  ===================================================================
  package org.apache.ojb.broker.util.batch;
  
  /* ====================================================================
   * The Apache Software License, Version 1.1
   *
   * Copyright (c) 2001 The Apache Software Foundation.  All rights
   * reserved.
   *
   * Redistribution and use in source and binary forms, with or without
   * modification, are permitted provided that the following conditions
   * are met:
   *
   * 1. Redistributions of source code must retain the above copyright
   *    notice, this list of conditions and the following disclaimer.
   *
   * 2. Redistributions in binary form must reproduce the above copyright
   *    notice, this list of conditions and the following disclaimer in
   *    the documentation and/or other materials provided with the
   *    distribution.
   *
   * 3. The end-user documentation included with the redistribution,
   *    if any, must include the following acknowledgment:
   *       "This product includes software developed by the
   *        Apache Software Foundation (http://www.apache.org/)."
   *    Alternately, this acknowledgment may appear in the software itself,
   *    if and wherever such third-party acknowledgments normally appear.
   *
   * 4. The names "Apache" and "Apache Software Foundation" and
   *    "Apache ObjectRelationalBridge" must not be used to endorse or promote products
   *    derived from this software without prior written permission. For
   *    written permission, please contact apache@apache.org.
   *
   * 5. Products derived from this software may not be called "Apache",
   *    "Apache ObjectRelationalBridge", nor may "Apache" appear in their name, without
   *    prior written permission of the Apache Software Foundation.
   *
   * THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESSED OR IMPLIED
   * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
   * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
   * DISCLAIMED.  IN NO EVENT SHALL THE APACHE SOFTWARE FOUNDATION OR
   * ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
   * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
   * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF
   * USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
   * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
   * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT
   * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
   * SUCH DAMAGE.
   * ====================================================================
   *
   * This software consists of voluntary contributions made by many
   * individuals on behalf of the Apache Software Foundation.  For more
   * information on the Apache Software Foundation, please see
   * <http://www.apache.org/>.
   */
  
  
  import java.lang.reflect.Method;
  import java.lang.reflect.InvocationTargetException;
  import java.sql.Connection;
  import java.sql.PreparedStatement;
  import java.sql.ResultSet;
  import java.sql.SQLException;
  import java.util.ArrayList;
  import java.util.Iterator;
  
  //#ifdef JDK13
  import java.lang.reflect.InvocationHandler;
  import java.lang.reflect.Proxy;
  //#else
  /*
  import com.develop.java.lang.reflect.InvocationHandler;
  import com.develop.java.lang.reflect.Proxy;
  */
  //#endif
  
  /**
   * The implementation of {@link java.reflect.InvocationHandler} which is used
   * to create dynamic proxy which will implement {@link java.sql.PreparedStatement} and
   * {@link BatchPreparedStatement}.
   *
   * @author Oleg Nitz (<a href="mailto:olegnitz@apache.org">olegnitz@apache.org</a>)
   */
  public class PreparedStatementInvocationHandler implements InvocationHandler
  {
  
      private final static Integer ONE = new Integer(1);
  
      private final static Method ADD_BATCH;
  
      static
      {
          Method addBatch = null;
  
          try
          {
              addBatch = PreparedStatement.class.getMethod("addBatch", null);
          }
          catch (Exception ex) 
          {
          }
          ADD_BATCH = addBatch;
      }
  
      private final BatchConnection _batchConn;
  
      private final String _sql;
  
      private ArrayList _methods = new ArrayList();
  
      private ArrayList _params = new ArrayList();
  
      public PreparedStatementInvocationHandler(BatchConnection batchConn, String sql)
      {
          _batchConn = batchConn;
          _sql = sql;
      }
  
      public Object invoke(Object proxy, Method method, Object[] args)
              throws Throwable
      {
          if (method.getName().equals("executeUpdate"))
          {
              _batchConn.nextExecuted(_sql);
              _methods.add(ADD_BATCH);
              _params.add(null);
              return ONE;
          }
          else if (method.getName().equals("doExecute"))
          {
              doExecute((Connection) args[0]);
              return null;
          }
          else
          {
              if (method.getReturnType() == Void.TYPE
                      && method.getName().startsWith("set"))
              {
                  _methods.add(method);
                  _params.add(args);
              }
              return null;
          }
      }
  
      /**
       * This method performs database modification at the very and of transaction.
       */
      private void doExecute(Connection conn) throws SQLException
      {
          PreparedStatement stmt;
          int size;
  
          size = _methods.size();
          if (size == 0)
          {
              return;
          }
          stmt = conn.prepareStatement(_sql);
          try
          {
              for (int i = 0; i < size; i++)
              {
                  try 
                  {
                      ((Method) _methods.get(i)).invoke(stmt, (Object[]) _params.get(i));
                  } 
                  catch (IllegalAccessException ex)
                  {
                      throw new SQLException(ex.toString());
                  } 
                  catch (InvocationTargetException ex) 
                  {
                      Throwable th = ex.getTargetException();
  
                      if (th == null) 
                      {
                          th = ex;
                      }
                      if (th instanceof SQLException) 
                      {
                          throw ((SQLException) th);
                      } 
                      else 
                      {
                          throw new SQLException(th.toString());
                      }
                  }
              }
              stmt.executeBatch();
          }
          finally
          {
              stmt.close();
              _methods.clear();
              _params.clear();
          }
      }
  }
  
  
  

Mime
View raw message