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

com.danidemi.jlubricant.springbatch.NamedJdbcCursorItemReader Maven / Gradle / Ivy

The newest version!
/*
 * Copyright 2006-2013 the original author or authors.
 *
 * 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.
 */
package com.danidemi.jlubricant.springbatch;

import java.sql.Connection;
import java.sql.PreparedStatement;
import java.sql.ResultSet;
import java.sql.SQLException;
import java.util.LinkedHashMap;
import java.util.List;
import java.util.Map;

import org.springframework.batch.item.database.AbstractCursorItemReader;
import org.springframework.jdbc.core.PreparedStatementCreator;
import org.springframework.jdbc.core.PreparedStatementCreatorFactory;
import org.springframework.jdbc.core.PreparedStatementSetter;
import org.springframework.jdbc.core.RowMapper;
import org.springframework.jdbc.core.SqlParameter;
import org.springframework.jdbc.core.namedparam.ExposedParsedSql;
import org.springframework.jdbc.core.namedparam.NamedParameterUtils;
import org.springframework.jdbc.core.namedparam.ParsedSql;
import org.springframework.jdbc.core.namedparam.SqlParameterSource;
import org.springframework.jdbc.support.JdbcUtils;
import org.springframework.util.Assert;
import org.springframework.util.ClassUtils;

/**
 * 

* Simple item reader implementation that opens a JDBC cursor and continually retrieves the * next row in the ResultSet. * This is highly based on Spring Batch's JdbcCursorItemReader. *

* *

* The statement used to open the cursor is created with the 'READ_ONLY' option since a non read-only * cursor may unnecessarily lock tables or rows. It is also opened with updatableRecords to false option, * which in turns is likely to impose a 'TYPE_FORWARD_ONLY' option. * * Currently the cursor will be opened using a separate connection which means that it will not participate * in any transactions created as part of the step processing. * It is not currently possible to change this behaviour. *

* *

* Each call to {@link #read()} will call the provided RowMapper, passing in the * ResultSet. *

* * @author Lucas Ward * @author Peter Zozom * @author Robert Kasanicky * @author Thomas Risberg * @author Daniele Demichelis */ @SuppressWarnings("rawtypes") public class NamedJdbcCursorItemReader extends AbstractCursorItemReader { PreparedStatement preparedStatement; PreparedStatementSetter preparedStatementSetter; String sql; RowMapper rowMapper; SqlParameterSource paramSource; /** Default maximum number of entries for this template's SQL cache: 256 */ public static final int DEFAULT_CACHE_LIMIT = 256; private int cacheLimit = DEFAULT_CACHE_LIMIT; /** Cache of original SQL String to ParsedSql representation */ private final Map parsedSqlCache = new LinkedHashMap(DEFAULT_CACHE_LIMIT, 0.75f, true) { @Override protected boolean removeEldestEntry(Map.Entry eldest) { return size() > getCacheLimit(); } }; public void setParamSource(SqlParameterSource paramSource) { this.paramSource = paramSource; } /** * Obtain a parsed representation of the given SQL statement. *

The default implementation uses an LRU cache with an upper limit * of 256 entries. * @param sql the original SQL * @return a representation of the parsed SQL statement */ protected ExposedParsedSql getParsedSql(String sql) { if (getCacheLimit() <= 0) { return new ExposedParsedSql( NamedParameterUtils.parseSqlStatement(sql) ); } synchronized (this.parsedSqlCache) { ExposedParsedSql parsedSql = this.parsedSqlCache.get(sql); if (parsedSql == null) { parsedSql = new ExposedParsedSql( NamedParameterUtils.parseSqlStatement(sql) ); this.parsedSqlCache.put(sql, parsedSql); } return parsedSql; } } /** * Specify the maximum number of entries for this template's SQL cache. * Default is 256. */ public void setCacheLimit(int cacheLimit) { this.cacheLimit = cacheLimit; } /** * Return the maximum number of entries for this template's SQL cache. */ public int getCacheLimit() { return this.cacheLimit; } public NamedJdbcCursorItemReader() { super(); setName(ClassUtils.getShortName(AbstractCursorItemReader.class)); } /** * Set the RowMapper to be used for all calls to read(). * * @param rowMapper */ public void setRowMapper(RowMapper rowMapper) { this.rowMapper = rowMapper; } /** * Set the SQL statement to be used when creating the cursor. This statement * should be a complete and valid SQL statement, as it will be run directly * without any modification. * * @param sql */ public void setSql(String sql) { this.sql = sql; } // /** // * Set the PreparedStatementSetter to use if any parameter values that need // * to be set in the supplied query. // * // * @param preparedStatementSetter // */ // public void setPreparedStatementSetter(PreparedStatementSetter preparedStatementSetter) { // this.preparedStatementSetter = preparedStatementSetter; // } /** * Assert that mandatory properties are set. * * @throws IllegalArgumentException if either data source or sql properties * not set. */ @Override public void afterPropertiesSet() throws Exception { super.afterPropertiesSet(); Assert.notNull(sql, "The SQL query must be provided"); Assert.notNull(rowMapper, "RowMapper must be provided"); } @Override protected void openCursor(Connection con) { //MyParsedSqlDel parsedSql = getParsedSql(sql); //String sqlToUse = NamedParameterUtils.substituteNamedParameters(parsedSql.getDelegate(), paramSource); //String theSql = sqlToUse; try { // if (isUseSharedExtendedConnection()) { // preparedStatement = con.prepareStatement(theSql, ResultSet.TYPE_FORWARD_ONLY, ResultSet.CONCUR_READ_ONLY, // ResultSet.HOLD_CURSORS_OVER_COMMIT); // } // else { // preparedStatement = con.prepareStatement(theSql, ResultSet.TYPE_FORWARD_ONLY, ResultSet.CONCUR_READ_ONLY); // } // applyStatementSettings(preparedStatement); // if (this.preparedStatementSetter != null) { // // // preparedStatementSetter.setValues(preparedStatement); // // // // // // } // this.rs = preparedStatement.executeQuery(); ParsedSql parsedSql1 = this.getParsedSql(sql).getDelegate(); String sqlToUse1 = NamedParameterUtils.substituteNamedParameters(parsedSql1, paramSource); Object[] params = NamedParameterUtils.buildValueArray(parsedSql1, paramSource, null); List declaredParameters = NamedParameterUtils.buildSqlParameterList(parsedSql1, paramSource); PreparedStatementCreatorFactory pscf = new PreparedStatementCreatorFactory(sqlToUse1, declaredParameters); pscf.setResultSetType( ResultSet.TYPE_FORWARD_ONLY ); pscf.setUpdatableResults(false); PreparedStatementCreator preparedStatementCreator = pscf.newPreparedStatementCreator(params); //con.prepareStatement(theSql, ResultSet.TYPE_FORWARD_ONLY, ResultSet.CONCUR_READ_ONLY); preparedStatement = preparedStatementCreator.createPreparedStatement(con); this.rs = preparedStatement.executeQuery(); handleWarnings(preparedStatement); } catch (SQLException se) { close(); throw getExceptionTranslator().translate("Executing query", getSql(), se); } } @Override @SuppressWarnings("unchecked") protected T readCursor(ResultSet rs, int currentRow) throws SQLException { return (T) rowMapper.mapRow(rs, currentRow); } /** * Close the cursor and database connection. */ @Override protected void cleanupOnClose() throws Exception { JdbcUtils.closeStatement(this.preparedStatement); } @Override public String getSql() { return this.sql; } }





© 2015 - 2025 Weber Informatics LLC | Privacy Policy