package org.ff4j.utils;
/*
* #%L
* ff4j-core
* %%
* Copyright (C) 2013 - 2015 Ff4J
* %%
* 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.
* #L%
*/
import java.sql.Connection;
import java.sql.DatabaseMetaData;
import java.sql.PreparedStatement;
import java.sql.ResultSet;
import java.sql.SQLException;
import java.sql.Statement;
import javax.sql.DataSource;
import org.ff4j.exception.FeatureAccessException;
/**
* Group utilities methods to work with low-level JDBC.
*
* @author Cedrick Lunven (@clunven)
*/
public class JdbcUtils {
private JdbcUtils() {
}
/**
* Check if target Table exist.
*
* @param tableName
* table to create
* @return
* if the table exist or not
*/
public static boolean isTableExist(DataSource ds, String tableName) {
Util.assertHasLength(tableName);
Connection sqlConn = null;
ResultSet rs = null;
try {
sqlConn = ds.getConnection();
DatabaseMetaData dbmd = sqlConn.getMetaData();
rs = dbmd.getTables(null, null, tableName, new String[] {"TABLE"});
return rs.next();
} catch (SQLException sqlEX) {
throw new FeatureAccessException("Cannot check table existence", sqlEX);
} finally {
closeResultSet(rs);
closeConnection(sqlConn);
}
}
/**
* Create table based on SQL.
*
* @param sqlQuery
* sql query
*/
public static void executeUpdate(DataSource ds, String sqlQuery) {
Util.assertHasLength(sqlQuery);
Connection sqlConn = null;
Statement sqlStmt = null;
try {
// Create connection
sqlConn = ds.getConnection();
sqlStmt = sqlConn.createStatement();
sqlStmt.executeUpdate(sqlQuery);
} catch (SQLException sqlEX) {
rollback(sqlConn);
throw new FeatureAccessException("Cannot execute SQL " + sqlQuery, sqlEX);
} finally {
closeStatement(sqlStmt);
closeConnection(sqlConn);
}
}
/**
* Build {@link PreparedStatement} from parameters
*
* @param query
* query template
* @param params
* current parameters
* @return working {@link PreparedStatement}
* @throws SQLException
* sql error when working with statement
*/
public static PreparedStatement buildStatement(Connection sqlConn, String query, String... params)
throws SQLException {
PreparedStatement ps = sqlConn.prepareStatement(query);
if (params != null && params.length > 0) {
for (int i = 0; i < params.length; i++) {
ps.setObject(i + 1, params[i]);
}
}
return ps;
}
/**
* Close resultset.
*
* @param rs
* target resultset
*/
public static void closeResultSet(ResultSet rs) {
try {
if (rs != null) {
rs.close();
}
} catch (SQLException e) {
throw new FeatureAccessException("An error occur when closing resultset", e);
}
}
/**
* Utility method to close statement properly.
*
* @param ps
*
*/
public static void closeStatement(PreparedStatement ps) {
try {
if (ps != null) {
ps.close();
}
} catch (SQLException e) {
throw new FeatureAccessException("An error occur when closing statement", e);
}
}
/**
* Utility method to close statement properly.
*
* @param ps
*
*/
public static void closeStatement(Statement ps) {
try {
if (ps != null) {
ps.close();
}
} catch (SQLException e) {
throw new FeatureAccessException("An error occur when closing statement", e);
}
}
/**
* Restore previous <code>autoCommit</code> setting and return connection to pool.
*
* @param sqlConnection
* @param previousAutoCommit original <code>autoCommit</code> setting of <code>sqlConnection</code>. Ignored when <code>
* null</code>
*/
public static void closeConnection(Connection sqlConnection, Boolean previousAutoCommit) {
try {
if (sqlConnection != null && !sqlConnection.isClosed()) {
if (previousAutoCommit != null) {
sqlConnection.setAutoCommit(previousAutoCommit);
}
sqlConnection.close();
}
} catch (SQLException e) {
throw new FeatureAccessException("An error occur when closing statement", e);
}
}
/**
* Return connection to pool.
*
* @param sqlConnection
*/
public static void closeConnection(Connection sqlConnection) {
closeConnection(sqlConnection, null);
}
/**
* Utility method to perform rollback in correct way.
*
* @param sqlConn
* current sql connection
*/
public static void rollback(Connection sqlConn) {
try {
if (sqlConn != null && !sqlConn.isClosed()) {
sqlConn.rollback();
}
} catch (SQLException e) {
throw new FeatureAccessException("Cannot rollback database, SQL ERROR", e);
}
}
}