All Downloads are FREE. Search and download functionalities are using the official Maven repository.

org.apache.ojb.broker.accesslayer.StatementsForClassImpl Maven / Gradle / Ivy

Go to download

ObJectRelationalBridge (OJB) is an Object/Relational mapping tool that allows transparent persistence for Java Objects against relational databases.

The newest version!
package org.apache.ojb.broker.accesslayer;

/* Copyright 2002-2005 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.
 */

import java.sql.Connection;
import java.sql.PreparedStatement;
import java.sql.ResultSet;
import java.sql.SQLException;
import java.sql.Statement;

import org.apache.ojb.broker.PersistenceBrokerSQLException;
import org.apache.ojb.broker.accesslayer.sql.SqlGenerator;
import org.apache.ojb.broker.accesslayer.sql.SqlGeneratorFactory;
import org.apache.ojb.broker.core.proxy.ProxyHelper;
import org.apache.ojb.broker.metadata.ClassDescriptor;
import org.apache.ojb.broker.metadata.JdbcConnectionDescriptor;
import org.apache.ojb.broker.metadata.ConnectionPoolDescriptor;
import org.apache.ojb.broker.platforms.Platform;
import org.apache.ojb.broker.platforms.PlatformException;
import org.apache.ojb.broker.platforms.PlatformFactory;
import org.apache.ojb.broker.query.Query;
import org.apache.ojb.broker.util.logging.Logger;
import org.apache.ojb.broker.util.logging.LoggerFactory;
import org.apache.ojb.broker.util.ExceptionHelper;

/**
 * This class serves as a cache for Statements that are
 * used for persistence operations on a given class.
 * @author Thomas Mahler
 * @version $Id: StatementsForClassImpl.java,v 1.1 2007-08-24 22:17:30 ewestfal Exp $
 */
public class StatementsForClassImpl implements StatementsForClassIF
{
    private Logger log = LoggerFactory.getLogger(StatementsForClassImpl.class);

    /**
     * sets the escape processing mode
     */
    // protected static boolean ESCAPEPROCESSING = false;

    protected final ClassDescriptor classDescriptor;
    protected final SqlGenerator sqlGenerator;
    protected final Platform platform;
    protected final Class clazz;
    protected final int fetchSize;
    private String deleteSql;
    private String insertSql;
    private String updateSql;
    private String selectByPKSql;

    /**
     * force use of JDBC 1.0 statement creation
     */
    protected boolean FORCEJDBC1_0 = false;

    public StatementsForClassImpl(
        final JdbcConnectionDescriptor jcd,
        final ClassDescriptor classDescriptor)
    {
        this.classDescriptor = classDescriptor;
        clazz = classDescriptor.getClassOfObject();
        platform = PlatformFactory.getPlatformFor(jcd);
        sqlGenerator = SqlGeneratorFactory.getInstance().createSqlGenerator(platform);

        final ConnectionPoolDescriptor cpd = jcd.getConnectionPoolDescriptor();
        fetchSize = cpd.getFetchSize();

        // detect JDBC level
        double level = jcd.getJdbcLevel();
        FORCEJDBC1_0 = level == 1.0;
    }

    /**
     * Answer true if a PreparedStatement has to be used
     * 
false for a CallableStatement */ protected boolean usePreparedDeleteStatement() { return !(classDescriptor.getDeleteProcedure() != null && classDescriptor.getDeleteProcedure().hasReturnValues()); } public PreparedStatement getDeleteStmt(Connection con) throws SQLException { if (deleteSql == null) { deleteSql = sqlGenerator.getPreparedDeleteStatement(classDescriptor).getStatement(); } try { return prepareStatement(con, deleteSql, Query.NOT_SCROLLABLE, usePreparedDeleteStatement(), StatementManagerIF.FETCH_SIZE_NOT_APPLICABLE); } catch (SQLException ex) { log.error("Can't prepare delete statement: " + deleteSql, ex); throw ex; } } public Statement getGenericStmt(Connection con, boolean scrollable) throws PersistenceBrokerSQLException { Statement stmt; try { stmt = createStatement(con, scrollable, StatementManagerIF.FETCH_SIZE_NOT_EXPLICITLY_SET); } catch (SQLException ex) { throw ExceptionHelper.generateException("Can't prepare statement:", ex, null, log); } return stmt; } /** * Answer true if a PreparedStatement has to be used *
false for a CallableStatement */ protected boolean usePreparedInsertStatement() { return !(classDescriptor.getInsertProcedure() != null && classDescriptor.getInsertProcedure().hasReturnValues()); } public PreparedStatement getInsertStmt(Connection con) throws SQLException { if (insertSql == null) { insertSql = sqlGenerator.getPreparedInsertStatement(classDescriptor).getStatement(); } try { return prepareStatement(con, insertSql, Query.NOT_SCROLLABLE, usePreparedInsertStatement(), StatementManagerIF.FETCH_SIZE_NOT_APPLICABLE); } catch (SQLException ex) { log.error("Can't prepare insert statement: " + insertSql, ex); throw ex; } } public PreparedStatement getPreparedStmt(Connection con, String sql, boolean scrollable, int explicitFetchSizeHint, boolean callableStmt) throws PersistenceBrokerSQLException { PreparedStatement stmt; try { stmt = prepareStatement(con, sql, scrollable, !callableStmt, explicitFetchSizeHint); } catch (SQLException ex) { throw ExceptionHelper.generateException("Can't prepare statement:", ex, sql, log); } return stmt; } public PreparedStatement getSelectByPKStmt(Connection con) throws SQLException { if (selectByPKSql == null) { selectByPKSql = sqlGenerator.getPreparedSelectByPkStatement(classDescriptor).getStatement(); } try { return prepareStatement(con, selectByPKSql, Query.NOT_SCROLLABLE, true, 1); } catch (SQLException ex) { log.error(ex); throw ex; } } /** * Answer true if a PreparedStatement has to be used *
false for a CallableStatement */ protected boolean usePreparedUpdateStatement() { return !(classDescriptor.getUpdateProcedure() != null && classDescriptor.getUpdateProcedure().hasReturnValues()); } public PreparedStatement getUpdateStmt(Connection con) throws SQLException { if (updateSql == null) { updateSql = sqlGenerator.getPreparedUpdateStatement(classDescriptor).getStatement(); } try { return prepareStatement(con, updateSql, Query.NOT_SCROLLABLE, usePreparedUpdateStatement(), StatementManagerIF.FETCH_SIZE_NOT_APPLICABLE); } catch (SQLException ex) { log.error("Can't prepare update statement: " + updateSql, ex); throw ex; } } /** * Prepares a statement with parameters that should work with most RDBMS. * * @param con the connection to utilize * @param sql the sql syntax to use when creating the statement. * @param scrollable determines if the statement will be scrollable. * @param createPreparedStatement if true, then a * {@link PreparedStatement} will be created. If false, then * a {@link java.sql.CallableStatement} will be created. * @param explicitFetchSizeHint will be used as fetchSize hint * (if applicable) if > 0 * * @return a statement that can be used to execute the syntax contained in * the sql argument. */ protected PreparedStatement prepareStatement(Connection con, String sql, boolean scrollable, boolean createPreparedStatement, int explicitFetchSizeHint) throws SQLException { PreparedStatement result; // if a JDBC1.0 driver is used the signature // prepareStatement(String, int, int) is not defined. // we then call the JDBC1.0 variant prepareStatement(String) try { // if necessary use JDB1.0 methods if (!FORCEJDBC1_0) { if (createPreparedStatement) { result = con.prepareStatement( sql, scrollable ? ResultSet.TYPE_SCROLL_INSENSITIVE : ResultSet.TYPE_FORWARD_ONLY, ResultSet.CONCUR_READ_ONLY); afterJdbc2CapableStatementCreate(result, explicitFetchSizeHint); } else { result = con.prepareCall( sql, scrollable ? ResultSet.TYPE_SCROLL_INSENSITIVE : ResultSet.TYPE_FORWARD_ONLY, ResultSet.CONCUR_READ_ONLY); } } else { if (createPreparedStatement) { result = con.prepareStatement(sql); } else { result = con.prepareCall(sql); } } } catch (AbstractMethodError err) { // this exception is raised if Driver is not JDBC 2.0 compliant log.warn("Used driver seems not JDBC 2.0 compatible, use the JDBC 1.0 mode", err); if (createPreparedStatement) { result = con.prepareStatement(sql); } else { result = con.prepareCall(sql); } FORCEJDBC1_0 = true; } catch (SQLException eSql) { // there are JDBC Driver that nominally implement JDBC 2.0, but // throw DriverNotCapableExceptions. If we catch one of these // we force usage of JDBC 1.0 if (eSql .getClass() .getName() .equals("interbase.interclient.DriverNotCapableException")) { log.warn("JDBC 2.0 problems with this interbase driver, we use the JDBC 1.0 mode"); if (createPreparedStatement) { result = con.prepareStatement(sql); } else { result = con.prepareCall(sql); } FORCEJDBC1_0 = true; } else { throw eSql; } } try { if (!ProxyHelper.isNormalOjbProxy(result)) // tomdz: What about VirtualProxy { platform.afterStatementCreate(result); } } catch (PlatformException e) { log.error("Platform dependend failure", e); } return result; } /** * Creates a statement with parameters that should work with most RDBMS. */ private Statement createStatement(Connection con, boolean scrollable, int explicitFetchSizeHint) throws java.sql.SQLException { Statement result; try { // if necessary use JDBC1.0 methods if (!FORCEJDBC1_0) { result = con.createStatement( scrollable ? ResultSet.TYPE_SCROLL_INSENSITIVE : ResultSet.TYPE_FORWARD_ONLY, ResultSet.CONCUR_READ_ONLY); afterJdbc2CapableStatementCreate(result, explicitFetchSizeHint); } else { result = con.createStatement(); } } catch (AbstractMethodError err) { // if a JDBC1.0 driver is used, the signature // createStatement(int, int) is not defined. // we then call the JDBC1.0 variant createStatement() log.warn("Used driver seems not JDBC 2.0 compatible, use the JDBC 1.0 mode", err); result = con.createStatement(); FORCEJDBC1_0 = true; } catch (SQLException eSql) { // there are JDBC Driver that nominally implement JDBC 2.0, but // throw DriverNotCapableExceptions. If we catch one of these // we force usage of JDBC 1.0 if (eSql.getClass().getName() .equals("interbase.interclient.DriverNotCapableException")) { log.warn("JDBC 2.0 problems with this interbase driver, we use the JDBC 1.0 mode"); FORCEJDBC1_0 = true; result = con.createStatement(); } else { throw eSql; } } try { platform.afterStatementCreate(result); } catch (PlatformException e) { log.error("Platform dependend failure", e); } return result; } private void afterJdbc2CapableStatementCreate(Statement stmt, int explicitFetchSizeHint) throws SQLException { if (stmt != null) { final int fetchSizeHint; if (explicitFetchSizeHint == StatementManagerIF.FETCH_SIZE_NOT_APPLICABLE) { fetchSizeHint = StatementManagerIF.FETCH_SIZE_NOT_APPLICABLE; } else if (explicitFetchSizeHint != StatementManagerIF.FETCH_SIZE_NOT_EXPLICITLY_SET) { fetchSizeHint = explicitFetchSizeHint; // specific for this Statement } else { fetchSizeHint = fetchSize; // connection pool default } if (fetchSizeHint > 0) { stmt.setFetchSize(fetchSize); } } } }




© 2015 - 2025 Weber Informatics LLC | Privacy Policy