org.apache.lucene.store.jdbc.support.JdbcTemplate.java Source code

Java tutorial

Introduction

Here is the source code for org.apache.lucene.store.jdbc.support.JdbcTemplate.java

Source

/*
 * Copyright 2004-2009 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 org.apache.lucene.store.jdbc.support;

import java.sql.CallableStatement;
import java.sql.Connection;
import java.sql.PreparedStatement;
import java.sql.ResultSet;
import java.sql.SQLException;
import java.sql.Statement;
import java.util.Arrays;
import javax.sql.DataSource;

import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
import org.apache.lucene.store.jdbc.JdbcDirectorySettings;
import org.apache.lucene.store.jdbc.JdbcStoreException;
import org.apache.lucene.store.jdbc.datasource.DataSourceUtils;

/**
 * Helper class that isused to encapsulate resource and transaction handling related to <code>DataSource</code>,
 * <code>Statement</code>, and <code>ResultSet</code>. {@link DataSourceUtils} is used to open/cose relevant
 * resources.
 *
 * @author kimchy
 * @see DataSourceUtils
 */
public class JdbcTemplate {

    private static final Log log = LogFactory.getLog(JdbcTemplate.class);

    /**
     * A callback interface used to initialize a Jdbc <code>PreparedStatement</code>.
     */
    public static interface PrepateStatementAwareCallback {

        /**
         * Initialize/Fill the given <code>PreparedStatement</code>.
         */
        void fillPrepareStatement(PreparedStatement ps) throws Exception;
    }

    /**
     * A callback used to retrieve data from a <code>ResultSet</code>.
     */
    public static interface ExecuteSelectCallback extends PrepateStatementAwareCallback {

        /**
         * Extract data from the <code>ResultSet</code> and an optional return value.
         */
        Object execute(ResultSet rs) throws Exception;
    }

    /**
     * A callback used to work with <code>CallableStatement</code>.
     */
    public static interface CallableStatementCallback {

        /**
         * initialize/Fill the <code>CallableStatement</code> before it is executed.
         */
        void fillCallableStatement(CallableStatement cs) throws Exception;

        /**
         * Read/Extract data from the result of the <code>CallableStatement</code> execution. CAn optionally
         * have a return value.
         */
        Object readCallableData(CallableStatement cs) throws Exception;
    }

    private DataSource dataSource;

    private JdbcDirectorySettings settings;

    /**
     * Creates a new <code>JdbcTemplate</code>.
     */
    public JdbcTemplate(DataSource dataSource, JdbcDirectorySettings settings) {
        this.dataSource = dataSource;
        this.settings = settings;
    }

    /**
     * A template method to execute a simple sql select statement. The jdbc
     * <code>Connection</code>, <code>PreparedStatement</code>, and <code>ResultSet</code>
     * are managed by the template.
     */
    public Object executeSelect(String sql, ExecuteSelectCallback callback) throws JdbcStoreException {
        Connection con = DataSourceUtils.getConnection(dataSource);
        PreparedStatement ps = null;
        ResultSet rs = null;
        try {
            ps = con.prepareStatement(sql);
            //            ps.setQueryTimeout(settings.getQueryTimeout());
            callback.fillPrepareStatement(ps);
            rs = ps.executeQuery();
            return callback.execute(rs);
        } catch (JdbcStoreException e) {
            if (log.isTraceEnabled()) {
                log.trace("Failed to execute sql [" + sql + "]", e);
            }
            throw e;
        } catch (Exception e) {
            if (log.isTraceEnabled()) {
                log.trace("Failed to execute sql [" + sql + "]", e);
            }
            throw new JdbcStoreException("Failed to execute sql [" + sql + "]", e);
        } finally {
            DataSourceUtils.closeResultSet(rs);
            DataSourceUtils.closeStatement(ps);
            DataSourceUtils.releaseConnection(con);
        }
    }

    /**
     * A template method to execute a simple sql callable statement. The jdbc
     * <code>Connection</code>, and <code>CallableStatement</code>
     * are managed by the template.
     */
    public Object executeCallable(String sql, CallableStatementCallback callback) throws JdbcStoreException {
        Connection con = DataSourceUtils.getConnection(dataSource);
        CallableStatement cs = null;
        try {
            cs = con.prepareCall(sql);
            //            cs.setQueryTimeout(settings.getQueryTimeout());
            callback.fillCallableStatement(cs);
            cs.execute();
            return callback.readCallableData(cs);
        } catch (JdbcStoreException e) {
            if (log.isTraceEnabled()) {
                log.trace("Failed to execute sql [" + sql + "]", e);
            }
            throw e;
        } catch (Exception e) {
            if (log.isTraceEnabled()) {
                log.trace("Failed to execute sql [" + sql + "]", e);
            }
            throw new JdbcStoreException("Failed to execute sql [" + sql + "]", e);
        } finally {
            DataSourceUtils.closeStatement(cs);
            DataSourceUtils.releaseConnection(con);
        }
    }

    /**
     * A template method to execute a simple sql update. The jdbc
     * <code>Connection</code>, and <code>PreparedStatement</code>
     * are managed by the template. A <code>PreparedStatement</code> can be used
     * to set values to the given sql.
     */
    public void executeUpdate(String sql, PrepateStatementAwareCallback callback) throws JdbcStoreException {
        Connection con = DataSourceUtils.getConnection(dataSource);
        PreparedStatement ps = null;
        try {
            ps = con.prepareStatement(sql);
            //            ps.setQueryTimeout(settings.getQueryTimeout());
            callback.fillPrepareStatement(ps);
            ps.executeUpdate();
        } catch (JdbcStoreException e) {
            if (log.isTraceEnabled()) {
                log.trace("Failed to execute sql [" + sql + "]", e);
            }
            throw e;
        } catch (Exception e) {
            if (log.isTraceEnabled()) {
                log.trace("Failed to execute sql [" + sql + "]", e);
            }
            throw new JdbcStoreException("Failed to execute sql [" + sql + "]", e);
        } finally {
            DataSourceUtils.closeStatement(ps);
            DataSourceUtils.releaseConnection(con);
        }
    }

    /**
     * A template method to execute a simpel sql update (with no need for data
     * initialization).
     */
    public void executeUpdate(String sql) throws JdbcStoreException {
        Connection con = DataSourceUtils.getConnection(dataSource);
        Statement statement = null;
        try {
            statement = con.createStatement();
            //            statement.setQueryTimeout(settings.getQueryTimeout());
            statement.executeUpdate(sql);
        } catch (SQLException e) {
            if (log.isTraceEnabled()) {
                log.trace("Failed to execute sql [" + sql + "]", e);
            }
            throw new JdbcStoreException("Failed to execute [" + sql + "]", e);
        } finally {
            DataSourceUtils.closeStatement(statement);
            DataSourceUtils.releaseConnection(con);
        }
    }

    /**
     * A template method to execute a set of sqls in batch.
     */
    public int[] executeBatch(String[] sqls) throws JdbcStoreException {
        Connection con = DataSourceUtils.getConnection(dataSource);
        Statement statement = null;
        try {
            statement = con.createStatement();
            //            statement.setQueryTimeout(settings.getQueryTimeout());
            for (String sql : sqls) {
                statement.addBatch(sql);
            }
            return statement.executeBatch();
        } catch (SQLException e) {
            if (log.isTraceEnabled()) {
                log.trace("Failed to execute sql [" + Arrays.toString(sqls) + "]", e);
            }
            throw new JdbcStoreException("Failed to execute [" + Arrays.toString(sqls) + "]", e);
        } finally {
            DataSourceUtils.closeStatement(statement);
            DataSourceUtils.releaseConnection(con);
        }
    }

    /**
     * A template method to execute that can execute the same sql several times using different
     * values set to it (in the <code>fillPrepareStatement</code>) callback).
     */
    public int[] executeBatch(String sql, PrepateStatementAwareCallback callback) throws JdbcStoreException {
        Connection con = DataSourceUtils.getConnection(dataSource);
        PreparedStatement ps = null;
        try {
            ps = con.prepareStatement(sql);
            //            ps.setQueryTimeout(settings.getQueryTimeout());
            callback.fillPrepareStatement(ps);
            return ps.executeBatch();
        } catch (JdbcStoreException e) {
            if (log.isTraceEnabled()) {
                log.trace("Failed to execute sql [" + sql + "]", e);
            }
            throw e;
        } catch (Exception e) {
            if (log.isTraceEnabled()) {
                log.trace("Failed to execute sql [" + sql + "]", e);
            }
            throw new JdbcStoreException("Failed to execute sql [" + sql + "]", e);
        } finally {
            DataSourceUtils.closeStatement(ps);
            DataSourceUtils.releaseConnection(con);
        }
    }
}