/* * The Kuali Financial System, a comprehensive financial management system for higher education. * * Copyright 2005-2014 The Kuali Foundation * * This program is free software: you can redistribute it and/or modify * it under the terms of the GNU Affero General Public License as * published by the Free Software Foundation, either version 3 of the * License, or (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU Affero General Public License for more details. * * You should have received a copy of the GNU Affero General Public License * along with this program. If not, see <http://www.gnu.org/licenses/>. */ package org.kuali.kfs.sys.batch.dataaccess.impl; import java.sql.PreparedStatement; import java.sql.ResultSet; import java.sql.SQLException; import java.util.ArrayList; import java.util.HashMap; import java.util.List; import java.util.Map; import org.kuali.kfs.sys.batch.dataaccess.PreparedStatementCachingDao; import org.kuali.rice.core.framework.persistence.jdbc.dao.PlatformAwareDaoBaseJdbc; import org.kuali.rice.krad.util.ObjectUtils; public abstract class AbstractPreparedStatementCachingDaoJdbc extends PlatformAwareDaoBaseJdbc implements PreparedStatementCachingDao { private static org.apache.log4j.Logger LOG = org.apache.log4j.Logger.getLogger(AbstractPreparedStatementCachingDaoJdbc.class); protected static final String RETRIEVE_PREFIX = "retrieve-"; protected static final String INSERT_PREFIX = "insert-"; protected static final String UPDATE_PREFIX = "update-"; protected abstract class JdbcWrapper<T> { protected abstract void populateStatement(PreparedStatement preparedStatement) throws SQLException; void update(Class<T> type, PreparedStatement preparedStatement) { try { populateStatement(preparedStatement); preparedStatement.executeUpdate(); } catch (SQLException e) { throw new RuntimeException("AbstractUpdatingPreparedStatementCachingDaoJdbc.UpdatingJdbcWrapper encountered exception during getObject method for type: " + type, e); } } } protected abstract class RetrievingJdbcWrapper<T> extends JdbcWrapper { protected abstract T extractResult(ResultSet resultSet) throws SQLException; public T get(Class<T> type) { T value = null; PreparedStatement statement = preparedStatementCache.get(RETRIEVE_PREFIX + type); try { populateStatement(statement); ResultSet resultSet = statement.executeQuery(); if (resultSet.next()) { value = extractResult(resultSet); if (resultSet.next()) { throw new RuntimeException("More that one row returned when selecting by primary key in AbstractRetrievingPreparedStatementCachingDaoJdbc.RetrievingJdbcWrapper for: " + type); } } resultSet.close(); } catch (SQLException e) { throw new RuntimeException("AbstractRetrievingPreparedStatementCachingDaoJdbc.RetrievingJdbcWrapper encountered exception during getObject method for type: " + type, e); } return value; } } /** * Retrieve list jdbc objects */ protected abstract class RetrievingListJdbcWrapper<T> extends JdbcWrapper { protected abstract T extractResult(ResultSet resultSet) throws SQLException; public List<T> get(Class<T> type) { List<T> resultList = new ArrayList<T>(); PreparedStatement statement = preparedStatementCache.get(RETRIEVE_PREFIX + type); try { populateStatement(statement); ResultSet resultSet = statement.executeQuery(); while (resultSet.next()) { resultList.add(extractResult(resultSet)); } resultSet.close(); } catch (SQLException e) { throw new RuntimeException("AbstractRetrievingPreparedStatementCachingDaoJdbc.RetrievingListJdbcWrapper encountered exception during getObject method for type: " + type, e); } return resultList; } } protected abstract class InsertingJdbcWrapper<T> extends JdbcWrapper { public void execute(Class<T> type) { update(type, preparedStatementCache.get(INSERT_PREFIX + type)); } } protected abstract class UpdatingJdbcWrapper<T> extends JdbcWrapper { public void execute(Class<T> type) { update(type, preparedStatementCache.get(UPDATE_PREFIX + type)); } } protected Map<String, PreparedStatement> preparedStatementCache; protected abstract Map<String, String> getSql(); public void initialize() { preparedStatementCache = new HashMap<String, PreparedStatement>(); try { for (String statementKey : getSql().keySet()) { preparedStatementCache.put(statementKey, getConnection().prepareStatement(getSql().get(statementKey))); } } catch (SQLException e) { throw new RuntimeException("Caught exception preparing statements in CachingDaoJdbc initialize method", e); } } public void destroy() { try { // this should never happen, but it did; so just in case. if (ObjectUtils.isNull(preparedStatementCache)) { LOG.error("preparedStatementCache is null. This shouldn't have happened."); return; } for (PreparedStatement preparedStatement : preparedStatementCache.values()) { preparedStatement.close(); } preparedStatementCache = null; } catch (SQLException e) { throw new RuntimeException("Caught exception closing statements in CachingDaoJdbc destroy method", e); } } }