/** * Copyright (C) 2014 - present by OpenGamma Inc. and the OpenGamma group of companies * * Please see distribution for license. */ package com.opengamma.util.db; import javax.sql.DataSource; import org.springframework.dao.DataAccessException; import org.springframework.jdbc.core.JdbcOperations; import org.springframework.jdbc.core.PreparedStatementCreator; import org.springframework.jdbc.core.SqlParameterValue; import org.springframework.jdbc.core.namedparam.NamedParameterJdbcTemplate; import org.springframework.jdbc.core.namedparam.SqlParameterSource; import org.springframework.jdbc.support.KeyHolder; /** * An extension of {@link NamedParameterJdbcTemplate} to handle Oracle. * <p> * This class adjusts string named parameters to a format suitable for Oracle database. * Specifically, it handle empty strings by converting them to a single whitespace. */ final class OracleNamedParameterJdbcTemplate extends NamedParameterJdbcTemplate { /** * Creates an instance. * * @param dataSource the JDBC DataSource to access */ public OracleNamedParameterJdbcTemplate(DataSource dataSource) { this(new OracleJdbcTemplate(dataSource)); } /** * Creates an instance. * * @param classicJdbcTemplate the classic Spring JdbcTemplate to wrap */ public OracleNamedParameterJdbcTemplate(JdbcOperations classicJdbcTemplate) { super(classicJdbcTemplate); } //------------------------------------------------------------------------- public int update( String sql, SqlParameterSource paramSource, KeyHolder generatedKeyHolder, String[] keyColumnNames) throws DataAccessException { SqlParameterSource decorated = new OracleSqlParameterSource(paramSource); return super.update(sql, decorated, generatedKeyHolder, keyColumnNames); } public int[] batchUpdate(String sql, SqlParameterSource[] batchArgs) { SqlParameterSource[] decorated = new SqlParameterSource[batchArgs.length]; for (int i = 0; i < batchArgs.length; i++) { decorated[i] = new OracleSqlParameterSource(batchArgs[i]); } return super.batchUpdate(sql, decorated); } @Override protected PreparedStatementCreator getPreparedStatementCreator(String sql, SqlParameterSource paramSource) { SqlParameterSource decorated = new OracleSqlParameterSource(paramSource); return super.getPreparedStatementCreator(sql, decorated); } //------------------------------------------------------------------------- @Override public String toString() { return "OracleNamedParameterJdbcTemplate:" + super.toString(); } //------------------------------------------------------------------------- /** * Parameter source adding Oracle string conversion. */ static final class OracleSqlParameterSource implements SqlParameterSource { // the underlying source private final SqlParameterSource _underlying; public OracleSqlParameterSource(SqlParameterSource underlying) { _underlying = underlying; } @Override public boolean hasValue(String paramName) { return _underlying.hasValue(paramName); } @Override public Object getValue(String paramName) throws IllegalArgumentException { Object value = _underlying.getValue(paramName); return toDatabaseFormat(value); } // only need to handle SqlParameterValue and String private static Object toDatabaseFormat(Object value) { if (value instanceof SqlParameterValue) { SqlParameterValue param = (SqlParameterValue) value; if (param.getValue() instanceof String) { String dbStr = Oracle11gDbDialect.INSTANCE.toDatabaseString((String) param.getValue()); value = new SqlParameterValue(param.getSqlType(), dbStr); } } else if (value instanceof String) { value = Oracle11gDbDialect.INSTANCE.toDatabaseString((String) value); } return value; } @Override public int getSqlType(String paramName) { return _underlying.getSqlType(paramName); } @Override public String getTypeName(String paramName) { return _underlying.getTypeName(paramName); } } }