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

org.jumpmind.db.sql.JdbcSqlTemplate Maven / Gradle / Ivy

There is a newer version: 3.5.19
Show newest version
/**
 * Licensed to JumpMind Inc under one or more contributor
 * license agreements.  See the NOTICE file distributed
 * with this work for additional information regarding
 * copyright ownership.  JumpMind Inc licenses this file
 * to you under the GNU General Public License, version 3.0 (GPLv3)
 * (the "License"); you may not use this file except in compliance
 * with the License.
 *
 * You should have received a copy of the GNU General Public License,
 * version 3.0 (GPLv3) along with this library; if not, see
 * .
 *
 * 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.jumpmind.db.sql;

import java.io.IOException;
import java.io.InputStream;
import java.io.Reader;
import java.lang.reflect.Method;
import java.math.BigDecimal;
import java.math.BigInteger;
import java.sql.Blob;
import java.sql.Clob;
import java.sql.Connection;
import java.sql.DatabaseMetaData;
import java.sql.PreparedStatement;
import java.sql.ResultSet;
import java.sql.ResultSetMetaData;
import java.sql.SQLException;
import java.sql.Statement;
import java.sql.Timestamp;
import java.sql.Types;
import java.util.Arrays;
import java.util.Date;
import java.util.HashSet;
import java.util.Map;
import java.util.Set;

import javax.sql.DataSource;

import org.apache.commons.io.IOUtils;
import org.jumpmind.db.model.TypeMap;
import org.jumpmind.db.platform.DatabaseInfo;
import org.jumpmind.exception.IoException;
import org.jumpmind.util.LinkedCaseInsensitiveMap;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.jdbc.core.SqlTypeValue;
import org.springframework.jdbc.core.StatementCreatorUtils;
import org.springframework.jdbc.support.lob.DefaultLobHandler;
import org.springframework.jdbc.support.lob.LobHandler;

public class JdbcSqlTemplate extends AbstractSqlTemplate implements ISqlTemplate {

    static final Logger log = LoggerFactory.getLogger(JdbcSqlTemplate.class);

    protected DataSource dataSource;

    protected boolean requiresAutoCommitFalseToSetFetchSize = false;

    protected SqlTemplateSettings settings;

    protected SymmetricLobHandler lobHandler;

    protected Boolean supportsGetGeneratedKeys = null;

    protected int[] primaryKeyViolationCodes;

    protected String[] primaryKeyViolationSqlStates;

    protected int[] foreignKeyViolationCodes;

    protected String[] foreignKeyViolationSqlStates;

    protected int isolationLevel;

    public JdbcSqlTemplate(DataSource dataSource, SqlTemplateSettings settings,
            SymmetricLobHandler lobHandler, DatabaseInfo databaseInfo) {
        this.dataSource = dataSource;
        this.settings = settings == null ? new SqlTemplateSettings() : settings;
        this.lobHandler = lobHandler == null ? new SymmetricLobHandler(new DefaultLobHandler())
                : lobHandler;
        this.isolationLevel = databaseInfo.getMinIsolationLevelToPreventPhantomReads();
    }

    protected Connection getConnection() throws SQLException {
        return this.dataSource.getConnection();
    }

    public DataSource getDataSource() {
        return dataSource;
    }

    public boolean isRequiresAutoCommitFalseToSetFetchSize() {
        return requiresAutoCommitFalseToSetFetchSize;
    }

    public void setSettings(SqlTemplateSettings settings) {
        this.settings = settings;
    }

    public SqlTemplateSettings getSettings() {
        return settings;
    }

    public SymmetricLobHandler getLobHandler() {
        return lobHandler;
    }

    public  ISqlReadCursor queryForCursor(String sql, ISqlRowMapper mapper, Object[] args,
            int[] types) {
        logSql(sql, args);
        return new JdbcSqlReadCursor(this, mapper, sql, args, types);
    }

    public int getIsolationLevel() {
        return isolationLevel;
    }

    public void setIsolationLevel(int isolationLevel) {
        this.isolationLevel = isolationLevel;
    }

    public  T queryForObject(final String sql, final Class clazz, final Object... args) {
        logSql(sql, args);
        return execute(new IConnectionCallback() {
            public T execute(Connection con) throws SQLException {
                T result = null;
                PreparedStatement ps = null;
                ResultSet rs = null;
                try {
                    ps = con.prepareStatement(expandSql(sql, args));
                    ps.setQueryTimeout(settings.getQueryTimeout());
                    setValues(ps, expandArgs(sql, args));
                    rs = ps.executeQuery();
                    if (rs.next()) {
                        result = getObjectFromResultSet(rs, clazz);
                    }
                } finally {
                    close(rs);
                    close(ps);
                }
                return result;
            }
        });
    }

    @Deprecated
    public byte[] queryForBlob(final String sql, final Object... args) {
        return queryForBlob(sql, -1, null, args);
    }

    public byte[] queryForBlob(final String sql, final int jdbcTypeCode, final String jdbcTypeName,
            final Object... args) {
        logSql(sql, args);
        return execute(new IConnectionCallback() {
            public byte[] execute(Connection con) throws SQLException {
                if (lobHandler.needsAutoCommitFalseForBlob(jdbcTypeCode, jdbcTypeName)) {
                    con.setAutoCommit(false);
                }
                byte[] result = null;
                PreparedStatement ps = null;
                ResultSet rs = null;
                try {
                    ps = con.prepareStatement(sql);
                    ps.setQueryTimeout(settings.getQueryTimeout());
                    setValues(ps, args);
                    rs = ps.executeQuery();
                    if (rs.next()) {
                        result = lobHandler.getBlobAsBytes(rs, 1, jdbcTypeCode, jdbcTypeName);
                    }
                } finally {
                    if (lobHandler.needsAutoCommitFalseForBlob(jdbcTypeCode, jdbcTypeName)
                            && con != null) {
                        con.setAutoCommit(true);
                    }
                    close(rs);
                    close(ps);
                }
                return result;
            }
        });
    }

    public String queryForClob(final String sql, final Object... args) {
        logSql(sql, args);
        return execute(new IConnectionCallback() {
            public String execute(Connection con) throws SQLException {
                String result = null;
                PreparedStatement ps = null;
                ResultSet rs = null;
                try {
                    ps = con.prepareStatement(sql);
                    ps.setQueryTimeout(settings.getQueryTimeout());
                    setValues(ps, args);
                    rs = ps.executeQuery();
                    if (rs.next()) {
                        result = lobHandler.getClobAsString(rs, 1);
                    }
                } finally {
                    close(rs);
                    close(ps);
                }
                return result;
            }
        });
    }

    public Map queryForMap(final String sql, final Object... args) {
        logSql(sql, args);
        return execute(new IConnectionCallback>() {
            public Map execute(Connection con) throws SQLException {
                Map result = null;
                PreparedStatement ps = null;
                ResultSet rs = null;
                try {
                    ps = con.prepareStatement(sql);
                    ps.setQueryTimeout(settings.getQueryTimeout());
                    if (args != null && args.length > 0) {
                        setValues(ps, args);
                    }
                    rs = ps.executeQuery();
                    if (rs.next()) {
                        ResultSetMetaData meta = rs.getMetaData();
                        int colCount = meta.getColumnCount();
                        result = new LinkedCaseInsensitiveMap(colCount);
                        for (int i = 1; i <= colCount; i++) {
                            String key = meta.getColumnName(i);
                            Object value = rs.getObject(i);
                            if (value instanceof Blob) {
                                Blob blob = (Blob) value;
                                try {
                                    value = IOUtils.toByteArray(blob.getBinaryStream());
                                } catch (IOException e) {
                                    throw new IoException(e);
                                }
                            } else if (value instanceof Clob) {
                                Clob clob = (Clob) value;
                                try {
                                    value = IOUtils.toByteArray(clob.getCharacterStream());
                                } catch (IOException e) {
                                    throw new IoException(e);
                                }
                            } else if (value != null) {
                                Class clazz = value.getClass();
                                Class superClazz = clazz.getSuperclass();
                                if (superClazz != null
                                        && superClazz.getName().equals("oracle.sql.Datum")) {
                                    try {
                                        Method method = superClazz.getMethod("toJdbc");
                                        value = method.invoke(value);
                                    } catch (Exception e) {
                                        throw new IllegalStateException(e);
                                    }
                                }
                            }
                            result.put(key, value);
                        }
                    }
                } finally {
                    close(rs);
                    close(ps);
                }
                return result;
            }
        });
    }

    public ISqlTransaction startSqlTransaction() {
        return new JdbcSqlTransaction(this);
    }

    public int update(final String sql, final Object[] args, final int[] types) {
        logSql(sql, args);
        return execute(new IConnectionCallback() {
            public Integer execute(Connection con) throws SQLException {
                if (args == null) {
                    Statement stmt = null;
                    try {
                        stmt = con.createStatement();
                        stmt.setQueryTimeout(settings.getQueryTimeout());
                        stmt.execute(sql);
                        return stmt.getUpdateCount();
                    } finally {
                        close(stmt);
                    }
                } else {
                    PreparedStatement ps = null;
                    try {
                        ps = con.prepareStatement(sql);
                        ps.setQueryTimeout(settings.getQueryTimeout());
                        if (types != null) {
                            setValues(ps, args, types, getLobHandler()
                                    .getDefaultHandler());
                        } else {
                            setValues(ps, args);
                        }
                        ps.execute();
                        return ps.getUpdateCount();
                    } finally {
                        close(ps);
                    }
                }
            }
        });
    }

    public int update(boolean autoCommit, boolean failOnError, int commitRate, String... sql) {
        return update(autoCommit, failOnError, commitRate, null, sql);
    }

    public int update(boolean autoCommit, boolean failOnError, int commitRate,
            ISqlResultsListener resultsListener, String... sql) {
        return this.update(autoCommit, failOnError, true, true,
                commitRate, resultsListener, new ListSqlStatementSource(sql));
    }

    public int update(final boolean autoCommit, final boolean failOnError, final boolean failOnDrops,
            final boolean failOnSequenceCreate, final int commitRate, final ISqlResultsListener resultsListener, final ISqlStatementSource source) {
        return execute(new IConnectionCallback() {
            public Integer execute(Connection con) throws SQLException {
                int totalUpdateCount = 0;
                boolean oldAutoCommitSetting = con.getAutoCommit();
                Statement stmt = null;
                try {
                    con.setAutoCommit(autoCommit);
                    stmt = con.createStatement();
                    int statementCount = 0;
                    for (String statement = source.readSqlStatement(); statement != null; statement = source
                            .readSqlStatement()) {
                        logSql(statement, null);
                        try {
                            boolean hasResults = stmt.execute(statement);
                            int updateCount = stmt.getUpdateCount();
                            totalUpdateCount += updateCount;
                            int rowsRetrieved = 0;
                            if (hasResults) {
                                ResultSet rs = null;
                                try {
                                    rs = stmt.getResultSet();
                                    while (rs.next()) {
                                        rowsRetrieved++;
                                    }
                                } finally {
                                    close(rs);
                                }
                            }
                            if (resultsListener != null) {
                                resultsListener.sqlApplied(statement, updateCount, rowsRetrieved,
                                        statementCount);
                            }
                            statementCount++;
                            if (statementCount % commitRate == 0 && !autoCommit) {
                                con.commit();
                            }
                        } catch (SQLException ex) {
                            boolean isDrop = statement.toLowerCase().trim().startsWith("drop");
                            boolean isSequenceCreate = statement.toLowerCase().trim().startsWith("create sequence");
                            if (resultsListener != null) {
                                resultsListener.sqlErrored(statement, translate(statement, ex),
                                        statementCount, isDrop, isSequenceCreate);
                            }

                            if ((isDrop && !failOnDrops) || (isSequenceCreate && !failOnSequenceCreate)) {
                                log.debug("{}.  Failed to execute: {}", ex.getMessage(), statement);
                            } else {
                                log.warn("{}.  Failed to execute: {}", ex.getMessage(), statement);
                                if (failOnError) {
                                    throw ex;
                                }
                            }

                        }
                    }

                    if (!autoCommit) {
                        con.commit();
                    }
                    return totalUpdateCount;
                } catch (SQLException ex) {
                    if (!autoCommit) {
                        con.rollback();
                    }
                    throw ex;
                } finally {
                    close(stmt);
                    con.setAutoCommit(oldAutoCommitSetting);
                }
            }
        });
    }

    public void testConnection() {
        execute(new IConnectionCallback() {
            public Boolean execute(Connection con) throws SQLException {
                return true;
            }
        });
    }

    public  T execute(IConnectionCallback callback) {
        Connection c = null;
        try {
            c = getConnection();
            return callback.execute(c);
        } catch (SQLException ex) {
            throw translate(ex);
        } finally {
            close(c);
        }
    }

    /**
     * Determine the column name to use. The column name is determined based on
     * a lookup using ResultSetMetaData.
     * 

* This method implementation takes into account recent clarifications * expressed in the JDBC 4.0 specification: *

* columnLabel - the label for the column specified with the SQL AS * clause. If the SQL AS clause was not specified, then the label is the * name of the column. * * @return the column name to use * @param resultSetMetaData * the current meta data to use * @param columnIndex * the index of the column for the look up * @throws SQLException * in case of lookup failure */ public static String lookupColumnName(ResultSetMetaData resultSetMetaData, int columnIndex) throws SQLException { String name = resultSetMetaData.getColumnLabel(columnIndex); if (name == null || name.length() < 1) { name = resultSetMetaData.getColumnName(columnIndex); } return name; } /** * Retrieve a JDBC column value from a ResultSet, using the most appropriate * value type. The returned value should be a detached value object, not * having any ties to the active ResultSet: in particular, it should not be * a Blob or Clob object but rather a byte array respectively String * representation. *

* Uses the getObject(index) method, but includes additional * "hacks" to get around Oracle 10g returning a non-standard object for its * TIMESTAMP datatype and a java.sql.Date for DATE columns * leaving out the time portion: These columns will explicitly be extracted * as standard java.sql.Timestamp object. * * @param rs * is the ResultSet holding the data * @param index * is the column index * @param readStringsAsBytes TODO * @return the value object * @throws SQLException * if thrown by the JDBC API * @see java.sql.Blob * @see java.sql.Clob * @see java.sql.Timestamp */ public static Object getResultSetValue(ResultSet rs, int index, boolean readStringsAsBytes) throws SQLException { ResultSetMetaData metaData = rs.getMetaData(); Object obj = null; int jdbcType = metaData.getColumnType(index); if (readStringsAsBytes && TypeMap.isTextType(jdbcType)) { byte[] bytes = rs.getBytes(index); if (bytes != null) { obj = new String(bytes); } } else { obj = rs.getObject(index); } String className = null; if (obj != null) { className = obj.getClass().getName(); } if (obj instanceof Blob) { Blob blob = (Blob) obj; InputStream is = blob.getBinaryStream(); try { obj = IOUtils.toByteArray(is); } catch (IOException e) { throw new SqlException(e); } finally { IOUtils.closeQuietly(is); } } else if (obj instanceof Clob) { Clob clob = (Clob) obj; Reader reader = clob.getCharacterStream(); try { obj = IOUtils.toString(reader); } catch (IOException e) { throw new SqlException(e); } finally { IOUtils.closeQuietly(reader); } } else if (className != null && ("oracle.sql.TIMESTAMP".equals(className))) { obj = rs.getTimestamp(index); } else if (className != null && "oracle.sql.TIMESTAMPTZ".equals(className)) { obj = rs.getString(index); } else if (className != null && className.startsWith("oracle.sql.DATE")) { String metaDataClassName = metaData.getColumnClassName(index); if ("java.sql.Timestamp".equals(metaDataClassName) || "oracle.sql.TIMESTAMP".equals(metaDataClassName)) { obj = rs.getTimestamp(index); } else { obj = rs.getDate(index); } } else if (obj instanceof java.sql.Date) { String metaDataClassName = metaData.getColumnClassName(index); if ("java.sql.Timestamp".equals(metaDataClassName)) { obj = rs.getTimestamp(index); } } else if (obj instanceof Timestamp) { String typeName = metaData.getColumnTypeName(index); if (typeName != null && typeName.equals("timestamptz")) { obj = rs.getString(index); } } return obj; } public static void close(ResultSet rs) { try { if (rs != null) { rs.close(); } } catch (SQLException ex) { } } public static void close(PreparedStatement ps) { try { if (ps != null) { ps.close(); } } catch (SQLException ex) { } } public static void close(Statement stmt) { try { if (stmt != null) { stmt.close(); } } catch (SQLException ex) { } } public static void close(boolean autoCommitValue, Connection c) { try { if (c != null) { c.setAutoCommit(autoCommitValue); } } catch (SQLException ex) { } finally { close(c); } } public static void close(boolean autoCommitValue, int transactionIsolationLevel, Connection c) { try { if (c != null) { c.setAutoCommit(autoCommitValue); if (c.getTransactionIsolation() != transactionIsolationLevel) { c.setTransactionIsolation(transactionIsolationLevel); } } } catch (SQLException ex) { } finally { close(c); } } public static void close(Connection c) { try { if (c != null) { c.close(); } } catch (SQLException ex) { } } public int getDatabaseMajorVersion() { return execute(new IConnectionCallback() { public Integer execute(Connection con) throws SQLException { return con.getMetaData().getDatabaseMajorVersion(); } }); } public int getDatabaseMinorVersion() { return execute(new IConnectionCallback() { public Integer execute(Connection con) throws SQLException { return con.getMetaData().getDatabaseMinorVersion(); } }); } public String getDatabaseProductName() { return execute(new IConnectionCallback() { public String execute(Connection con) throws SQLException { return con.getMetaData().getDatabaseProductName(); } }); } public boolean isStoresMixedCaseQuotedIdentifiers() { return execute(new IConnectionCallback() { public Boolean execute(Connection con) throws SQLException { return con.getMetaData().storesMixedCaseQuotedIdentifiers(); } }); } public boolean isStoresUpperCaseIdentifiers() { return execute(new IConnectionCallback() { public Boolean execute(Connection con) throws SQLException { return con.getMetaData().storesUpperCaseIdentifiers(); } }); } public boolean isStoresLowerCaseIdentifiers() { return execute(new IConnectionCallback() { public Boolean execute(Connection con) throws SQLException { return con.getMetaData().storesLowerCaseIdentifiers(); } }); } public String getDatabaseProductVersion() { return execute(new IConnectionCallback() { public String execute(Connection con) throws SQLException { return con.getMetaData().getDatabaseProductVersion(); } }); } public String getDriverName() { return execute(new IConnectionCallback() { public String execute(Connection con) throws SQLException { return con.getMetaData().getDriverName(); } }); } public String getDriverVersion() { return execute(new IConnectionCallback() { public String execute(Connection con) throws SQLException { return con.getMetaData().getDriverVersion(); } }); } public Set getSqlKeywords() { return execute(new IConnectionCallback>() { public Set execute(Connection con) throws SQLException { DatabaseMetaData sqlTemplateData = con.getMetaData(); return new HashSet(Arrays.asList(sqlTemplateData.getSQLKeywords() .split(","))); } }); } public boolean supportsGetGeneratedKeys() { if (supportsGetGeneratedKeys == null) { supportsGetGeneratedKeys = execute(new IConnectionCallback() { public Boolean execute(Connection con) throws SQLException { return con.getMetaData().supportsGetGeneratedKeys(); } }); } return supportsGetGeneratedKeys; } public boolean supportsReturningKeys() { return false; } protected boolean allowsNullForIdentityColumn() { return true; } protected String getSelectLastInsertIdSql(String sequenceName) { throw new UnsupportedOperationException(); } public long insertWithGeneratedKey(final String sql, final String column, final String sequenceName, final Object[] args, final int[] types) { return execute(new IConnectionCallback() { public Long execute(Connection conn) throws SQLException { return insertWithGeneratedKey(conn, sql, column, sequenceName, args, types); } }); } protected long insertWithGeneratedKey(Connection conn, String sql, String column, String sequenceName, Object[] args, int[] types) throws SQLException { long key = 0; PreparedStatement ps = null; try { boolean supportsGetGeneratedKeys = supportsGetGeneratedKeys(); boolean supportsReturningKeys = supportsReturningKeys(); if (allowsNullForIdentityColumn()) { if (supportsGetGeneratedKeys) { ps = conn.prepareStatement(sql, new int[] { 1 }); } else if (supportsReturningKeys) { ps = conn.prepareStatement(sql + " returning " + column); } else { ps = conn.prepareStatement(sql); } } else { String replaceSql = sql.replaceFirst("\\([\"|\\w]*,", "(").replaceFirst("\\(null,", "("); if (supportsGetGeneratedKeys) { ps = conn.prepareStatement(replaceSql, Statement.RETURN_GENERATED_KEYS); } else { ps = conn.prepareStatement(replaceSql); } } ps.setQueryTimeout(settings.getQueryTimeout()); setValues(ps, args, types, lobHandler.getDefaultHandler()); ResultSet rs = null; if (supportsGetGeneratedKeys) { ps.execute(); try { rs = ps.getGeneratedKeys(); if (rs.next()) { key = rs.getLong(1); } } finally { close(rs); } } else if (supportsReturningKeys) { try { rs = ps.executeQuery(); if (rs.next()) { key = rs.getLong(1); } } finally { close(rs); } } else { Statement st = null; ps.execute(); try { st = conn.createStatement(); rs = st.executeQuery(getSelectLastInsertIdSql(sequenceName)); if (rs.next()) { key = rs.getLong(1); } } finally { close(rs); close(st); } } } finally { close(ps); } return key; } public boolean isUniqueKeyViolation(Throwable ex) { boolean primaryKeyViolation = false; if (primaryKeyViolationCodes != null || primaryKeyViolationSqlStates != null) { SQLException sqlEx = findSQLException(ex); if (sqlEx != null) { if (primaryKeyViolationCodes != null) { int errorCode = sqlEx.getErrorCode(); for (int primaryKeyViolationCode : primaryKeyViolationCodes) { if (primaryKeyViolationCode == errorCode) { primaryKeyViolation = true; break; } } } if (primaryKeyViolationSqlStates != null) { String sqlState = sqlEx.getSQLState(); if (sqlState != null) { for (String primaryKeyViolationSqlState : primaryKeyViolationSqlStates) { if (primaryKeyViolationSqlState != null && primaryKeyViolationSqlState.equals(sqlState)) { primaryKeyViolation = true; break; } } } } } } return primaryKeyViolation; } public boolean isForeignKeyViolation(Throwable ex) { boolean foreignKeyViolation = false; if (foreignKeyViolationCodes != null || foreignKeyViolationSqlStates != null) { SQLException sqlEx = findSQLException(ex); if (sqlEx != null) { if (foreignKeyViolationCodes != null) { int errorCode = sqlEx.getErrorCode(); for (int foreignKeyViolationCode : foreignKeyViolationCodes) { if (foreignKeyViolationCode == errorCode) { foreignKeyViolation = true; break; } } } if (foreignKeyViolationSqlStates != null) { String sqlState = sqlEx.getSQLState(); if (sqlState != null) { for (String foreignKeyViolationSqlState : foreignKeyViolationSqlStates) { if (foreignKeyViolationSqlState != null && foreignKeyViolationSqlState.equals(sqlState)) { foreignKeyViolation = true; break; } } } } } } return foreignKeyViolation; } protected SQLException findSQLException(Throwable ex) { if (ex instanceof SQLException) { return (SQLException) ex; } else { Throwable cause = ex.getCause(); if (cause != null && !cause.equals(ex)) { return findSQLException(cause); } } return null; } @SuppressWarnings("unchecked") public T getObjectFromResultSet(ResultSet rs, Class clazz) throws SQLException { T result; if (Date.class.isAssignableFrom(clazz)) { result = (T) rs.getTimestamp(1); } else if (String.class.isAssignableFrom(clazz)) { result = (T) rs.getString(1); } else if (Long.class.isAssignableFrom(clazz)) { result = (T)new Long(rs.getLong(1)); } else if (Integer.class.isAssignableFrom(clazz)) { result = (T)new Integer(rs.getInt(1)); } else if (Float.class.isAssignableFrom(clazz)) { result = (T)new Float(rs.getFloat(1)); } else if (Double.class.isAssignableFrom(clazz)) { result = (T)new Double(rs.getDouble(1)); } else if (BigDecimal.class.isAssignableFrom(clazz)) { result = (T)rs.getBigDecimal(1); } else { result = (T) rs.getObject(1); } return result; } public void setValues(PreparedStatement ps, Object[] args, int[] argTypes, LobHandler lobHandler) throws SQLException { for (int i = 1; i <= args.length; i++) { Object arg = args[i - 1]; int argType = argTypes != null && argTypes.length >= i ? argTypes[i - 1] : SqlTypeValue.TYPE_UNKNOWN; if (argType == Types.BLOB && lobHandler != null && arg instanceof byte[]) { lobHandler.getLobCreator().setBlobAsBytes(ps, i, (byte[]) arg); } else if (argType == Types.BLOB && lobHandler != null && arg instanceof String) { lobHandler.getLobCreator().setBlobAsBytes(ps, i, arg.toString().getBytes()); } else if (argType == Types.CLOB && lobHandler != null) { lobHandler.getLobCreator().setClobAsString(ps, i, (String) arg); } else if ((argType == Types.DECIMAL || argType == Types.NUMERIC) && arg != null) { setDecimalValue(ps, i, arg, argType); } else { StatementCreatorUtils.setParameterValue(ps, i, verifyArgType(arg, argType), arg); } } } protected void setDecimalValue(PreparedStatement ps, int i, Object arg, int argType) throws SQLException { StatementCreatorUtils.setParameterValue(ps, i, verifyArgType(arg, argType), arg); } protected int verifyArgType(Object arg, int argType) { if (argType == -101 || argType == Types.OTHER) { return SqlTypeValue.TYPE_UNKNOWN; } else if ((argType == Types.INTEGER && arg instanceof BigInteger) || (argType == Types.BIGINT && arg instanceof BigDecimal)) { return Types.DECIMAL; } else { return argType; } } public void setValues(PreparedStatement ps, Object[] args) throws SQLException { if (args != null) { for (int i = 0; i < args.length; i++) { Object arg = args[i]; doSetValue(ps, i + 1, arg); } } } /** * Set the value for prepared statements specified parameter index using the * passed in value. This method can be overridden by sub-classes if needed. * * @param ps * the PreparedStatement * @param parameterPosition * index of the parameter position * @param argValue * the value to set * @throws SQLException */ public void doSetValue(PreparedStatement ps, int parameterPosition, Object argValue) throws SQLException { StatementCreatorUtils.setParameterValue(ps, parameterPosition, SqlTypeValue.TYPE_UNKNOWN, argValue); } }