/*
* CDDL HEADER START
*
* The contents of this file are subject to the terms of the
* Common Development and Distribution License (the "License").
* You may not use this file except in compliance with the License.
*
* See LICENSE.txt included in this distribution for the specific
* language governing permissions and limitations under the License.
*
* When distributing Covered Code, include this CDDL HEADER in each
* file and include the License file at LICENSE.txt.
* If applicable, add the following below this CDDL HEADER, with the
* fields enclosed by brackets "[]" replaced with your own identifying
* information: Portions Copyright [yyyy] [name of copyright owner]
*
* CDDL HEADER END
*/
/*
* Copyright (c) 2009, 2012, Oracle and/or its affiliates. All rights reserved.
*/
package org.opensolaris.opengrok.jdbc;
import java.sql.Connection;
import java.sql.DatabaseMetaData;
import java.sql.PreparedStatement;
import java.sql.SQLException;
import java.sql.Statement;
import java.util.HashMap;
import java.util.Map;
/**
* Class that manages the resources associated with a database connection.
* This includes a cache of {@code PreparedStatement}s.
*/
public class ConnectionResource {
/** The connection to the database. */
private final Connection conn;
/** Statement cache. */
private final Map<StatementCreator, PreparedStatement> statements =
new HashMap<StatementCreator, PreparedStatement>();
/**
* Create a new {@code ConnectionResource} instance.
* @param manager the {@code ConnectionManager} that created this object
* @throws SQLException if an error occurs when connecting to the database
*/
ConnectionResource(ConnectionManager manager) throws SQLException {
conn = manager.openConnection();
conn.setAutoCommit(false);
}
/**
* Check if the connection is still valid.
* @return {@code true} if the connection is valid, {@code false} if not
* @throws SQLException if a database error occurs
*/
public boolean isValid() throws SQLException {
// Check whether the connection is valid. Assume that the connection
// is lost if there's no response after 10 seconds. (Will normally
// return immediately if the connection is lost, but use a timeout
// in case of odd network issues.)
return conn.isValid(10);
}
/**
* Commit the transaction.
* @throws SQLException if a database error occurs
*/
public void commit() throws SQLException {
conn.commit();
}
/**
* Abort the transaction.
* @throws SQLException if a database error occurs
*/
public void rollback() throws SQLException {
conn.rollback();
}
/**
* Get a {@code PreparedStatement} as defined by the specified
* {@code StatementCreator}. If it is the first time the statement
* creator is used on this {@code ConnectionResource}, the creator's
* {@link StatementCreator#create(Connection)} method is called to
* create a new {@code PreparedStatement}. This statement is cached,
* so that on subsequent calls with the same statement creator, the same
* {@code PreparedStatement} will be returned.
*
* @param creator object that specifies how to create the statement if
* necessary
* @return a {@code PreparedStatement} object
* @throws SQLException if a database error occurs
*/
public PreparedStatement getStatement(StatementCreator creator)
throws SQLException {
PreparedStatement ps = statements.get(creator);
if (ps == null || ps.isClosed()) {
ps = creator.create(conn);
statements.put(creator, ps);
}
return ps;
}
/**
* Create a new {@code Statement} object.
* @return a {@code Statement} object
* @throws java.sql.SQLException
*/
public Statement createStatement() throws SQLException {
return conn.createStatement();
}
/**
* Prepare a statement. This method should only be used to prepare
* statements that are used infrequently. If a statement is likely to
* be used frequently, a {@code StatementCreator} object should be
* created for it, and the method {@link #getStatement(StatementCreator)}
* should be used instead.
*
* @param sql the SQL text to compile
* @return a prepared statement
* @throws SQLException if a database error occurs
*/
public PreparedStatement prepareStatement(String sql) throws SQLException {
return conn.prepareStatement(sql);
}
/**
* Get a meta-data object for the underlying connection.
*
* @return a {@code DatabaseMetaData} object
* @throws SQLException if a database error occurs
*/
public DatabaseMetaData getMetaData() throws SQLException {
return conn.getMetaData();
}
}