DbPreparedStatement.java
/*
* This file is part of Waarp Project (named also Waarp or GG).
*
* Copyright (c) 2019, Waarp SAS, and individual contributors by the @author
* tags. See the COPYRIGHT.txt in the distribution for a full listing of
* individual contributors.
*
* All Waarp Project is free software: you can redistribute it and/or
* modify it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or (at your
* option) any later version.
*
* Waarp 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 General Public License for more details.
*
* You should have received a copy of the GNU General Public License along with
* Waarp . If not, see <http://www.gnu.org/licenses/>.
*/
package org.waarp.common.database;
import org.waarp.common.database.exception.WaarpDatabaseNoConnectionException;
import org.waarp.common.database.exception.WaarpDatabaseSqlException;
import org.waarp.common.logging.WaarpLogger;
import org.waarp.common.logging.WaarpLoggerFactory;
import java.sql.PreparedStatement;
import java.sql.ResultSet;
import java.sql.SQLException;
/**
* Class to handle PrepareStatement
*/
public class DbPreparedStatement {
/**
* Internal Logger
*/
private static final WaarpLogger logger =
WaarpLoggerFactory.getLogger(DbPreparedStatement.class);
private static final String SQL_EXCEPTION_PREPARED_STATEMENT_NO_SESSION =
"SQL Exception PreparedStatement no session";
private static final String PREPARED_STATEMENT_NO_SESSION =
"PreparedStatement no session";
private static final String PREPARED_STATEMENT_NO_REQUEST =
"PreparedStatement no request";
/**
* Internal PreparedStatement
*/
private PreparedStatement preparedStatement;
/**
* The Associated request
*/
private String request;
/**
* Is this PreparedStatement ready
*/
private boolean isReady;
/**
* The associated resultSet
*/
private ResultSet rs;
/**
* The associated DB session
*/
private final DbSession ls;
/**
* Create a DbPreparedStatement from DbSession object
*
* @param ls
*
* @throws WaarpDatabaseNoConnectionException
*/
public DbPreparedStatement(final DbSession ls)
throws WaarpDatabaseNoConnectionException {
if (ls == null) {
logger.error(SQL_EXCEPTION_PREPARED_STATEMENT_NO_SESSION);
throw new WaarpDatabaseNoConnectionException(
PREPARED_STATEMENT_NO_SESSION);
}
if (ls.isDisActive()) {
logger.debug("DisActive: {}", ls.getAdmin().getServer());
ls.checkConnection();
}
this.ls = ls;
rs = null;
preparedStatement = null;
setReady(false);
}
/**
* Create a DbPreparedStatement from DbSession object and a request
*
* @param ls
* @param request
*
* @throws WaarpDatabaseNoConnectionException
* @throws WaarpDatabaseSqlException
*/
public DbPreparedStatement(final DbSession ls, final String request)
throws WaarpDatabaseNoConnectionException, WaarpDatabaseSqlException {
if (ls == null) {
logger.error(SQL_EXCEPTION_PREPARED_STATEMENT_NO_SESSION);
throw new WaarpDatabaseNoConnectionException(
PREPARED_STATEMENT_NO_SESSION);
}
if (ls.isDisActive()) {
ls.checkConnection();
}
this.ls = ls;
rs = null;
setReady(false);
preparedStatement = null;
if (request == null) {
logger.error(PREPARED_STATEMENT_NO_REQUEST);
throw new WaarpDatabaseNoConnectionException(
PREPARED_STATEMENT_NO_REQUEST);
}
try {
preparedStatement = this.ls.getConn().prepareStatement(request);
this.request = request;
setReady(true);
} catch (final SQLException e) {
ls.checkConnection();
try {
preparedStatement = this.ls.getConn().prepareStatement(request);
this.request = request;
setReady(true);
} catch (final SQLException e1) {
logger.error("SQL Exception PreparedStatement: " + request + ' ' +
e.getMessage());
DbConstant.error(e);
preparedStatement = null;
setReady(false);
throw new WaarpDatabaseSqlException("SQL Exception PreparedStatement",
e);
}
}
}
/**
* Create a DbPreparedStatement from DbSession object and a request
*
* @param ls
* @param request
* @param nbFetch the number of pre fetch rows
*
* @throws WaarpDatabaseNoConnectionException
* @throws WaarpDatabaseSqlException
*/
public DbPreparedStatement(final DbSession ls, final String request,
final int nbFetch)
throws WaarpDatabaseNoConnectionException, WaarpDatabaseSqlException {
if (ls == null) {
logger.error(SQL_EXCEPTION_PREPARED_STATEMENT_NO_SESSION);
throw new WaarpDatabaseNoConnectionException(
PREPARED_STATEMENT_NO_SESSION);
}
if (ls.isDisActive()) {
ls.checkConnection();
}
this.ls = ls;
rs = null;
setReady(false);
preparedStatement = null;
if (request == null) {
logger.error(PREPARED_STATEMENT_NO_REQUEST);
throw new WaarpDatabaseNoConnectionException(
PREPARED_STATEMENT_NO_SESSION);
}
try {
preparedStatement = this.ls.getConn().prepareStatement(request);
this.request = request;
preparedStatement.setFetchSize(nbFetch);
setReady(true);
} catch (final SQLException e) {
ls.checkConnection();
try {
preparedStatement = this.ls.getConn().prepareStatement(request);
this.request = request;
preparedStatement.setFetchSize(nbFetch);
setReady(true);
} catch (final SQLException e1) {
logger.error("SQL Exception PreparedStatement: " + request + ' ' +
e.getMessage());
DbConstant.error(e);
preparedStatement = null;
setReady(false);
throw new WaarpDatabaseSqlException("SQL Exception PreparedStatement",
e);
}
}
}
/**
* Create a preparedStatement from request
*
* @param requestarg
*
* @throws WaarpDatabaseNoConnectionException
* @throws WaarpDatabaseSqlException
*/
public final void createPrepareStatement(final String requestarg)
throws WaarpDatabaseNoConnectionException, WaarpDatabaseSqlException {
if (requestarg == null) {
logger.error(PREPARED_STATEMENT_NO_REQUEST);
throw new WaarpDatabaseNoConnectionException(
PREPARED_STATEMENT_NO_REQUEST);
}
if (preparedStatement != null) {
realClose();
}
if (rs != null) {
close();
}
if (ls.isDisActive()) {
logger.debug("DisActive: {}", ls.getAdmin().getServer());
ls.checkConnection();
}
try {
preparedStatement = ls.getConn().prepareStatement(requestarg);
request = requestarg;
setReady(true);
} catch (final SQLException e) {
ls.checkConnection();
try {
preparedStatement = ls.getConn().prepareStatement(requestarg);
request = requestarg;
setReady(true);
} catch (final SQLException e1) {
logger.error(
"SQL Exception createPreparedStatement from {}:" + requestarg +
' ' + e.getMessage(), ls.getAdmin().getServer());
DbConstant.error(e);
realClose();
preparedStatement = null;
setReady(false);
throw new WaarpDatabaseSqlException(
"SQL Exception createPreparedStatement: " + requestarg, e);
}
}
}
/**
* In case of closing database connection, it is possible to reopen a long
* term preparedStatement as it was at
* creation.
*
* @throws WaarpDatabaseSqlException
* @throws WaarpDatabaseNoConnectionException
*/
public final void recreatePreparedStatement()
throws WaarpDatabaseNoConnectionException, WaarpDatabaseSqlException {
createPrepareStatement(request);
}
/**
* Execute a Select preparedStatement
*
* @throws WaarpDatabaseNoConnectionException
* @throws WaarpDatabaseSqlException
*/
public final void executeQuery()
throws WaarpDatabaseNoConnectionException, WaarpDatabaseSqlException {
if (preparedStatement == null) {
logger.error("executeQuery no request");
throw new WaarpDatabaseNoConnectionException("executeQuery no request");
}
if (rs != null) {
close();
}
if (ls.isDisActive()) {
ls.checkConnection();
throw new WaarpDatabaseSqlException(
"Request cannot be executed since connection was recreated between: " +
request);
}
try {
rs = preparedStatement.executeQuery();
} catch (final SQLException e) {
logger.error(
"SQL Exception executeQuery:" + request + ' ' + e.getMessage());
DbConstant.error(e);
close();
rs = null;
ls.checkConnectionNoException();
throw new WaarpDatabaseSqlException(
"SQL Exception executeQuery: " + request, e);
}
}
/**
* Execute the Update/Insert/Delete preparedStatement
*
* @return the number of row
*
* @throws WaarpDatabaseNoConnectionException
* @throws WaarpDatabaseSqlException
*/
public final int executeUpdate()
throws WaarpDatabaseNoConnectionException, WaarpDatabaseSqlException {
if (preparedStatement == null) {
logger.error("executeUpdate no request");
throw new WaarpDatabaseNoConnectionException("executeUpdate no request");
}
if (rs != null) {
close();
}
if (ls.isDisActive()) {
ls.checkConnection();
throw new WaarpDatabaseSqlException(
"Request cannot be executed since connection was recreated between:" +
request);
}
final int retour;
try {
retour = preparedStatement.executeUpdate();
} catch (final SQLException e) {
logger.error(
"SQL Exception executeUpdate:" + request + ' ' + e.getMessage());
logger.debug("SQL Exception full stack trace", e);
DbConstant.error(e);
ls.checkConnectionNoException();
throw new WaarpDatabaseSqlException(
"SQL Exception executeUpdate: " + request, e);
}
return retour;
}
/**
* Close the resultSet if any
*/
public final void close() {
if (rs != null) {
try {
rs.close();
} catch (final SQLException ignored) {
// nothing
}
rs = null;
}
}
/**
* Really close the preparedStatement and the resultSet if any
*/
public final void realClose() {
close();
if (preparedStatement != null) {
if (ls.isDisActive()) {
ls.checkConnectionNoException();
}
try {
preparedStatement.close();
} catch (final SQLException e) {
ls.checkConnectionNoException();
}
preparedStatement = null;
}
setReady(false);
}
/**
* Move the cursor to the next result
*
* @return True if there is a next result, else False
*
* @throws WaarpDatabaseNoConnectionException
* @throws WaarpDatabaseSqlException
*/
public final boolean getNext()
throws WaarpDatabaseNoConnectionException, WaarpDatabaseSqlException {
if (rs == null) {
logger.error("SQL ResultSet is Null into getNext");
throw new WaarpDatabaseNoConnectionException(
"SQL ResultSet is Null into getNext");
}
if (ls.isDisActive()) {
ls.checkConnection();
throw new WaarpDatabaseSqlException(
"Request cannot be executed since connection was recreated between");
}
try {
return rs.next();
} catch (final SQLException e) {
logger.error("SQL Exception to getNextRow" +
(request != null? " [" + request + ']' : "") + ' ' +
e.getMessage());
DbConstant.error(e);
ls.checkConnectionNoException();
throw new WaarpDatabaseSqlException(
"SQL Exception to getNextRow: " + request, e);
}
}
/**
* @return The resultSet (can be used in conjunction of getNext())
*
* @throws WaarpDatabaseNoConnectionException
*/
public final ResultSet getResultSet()
throws WaarpDatabaseNoConnectionException {
if (rs == null) {
throw new WaarpDatabaseNoConnectionException(
"SQL ResultSet is Null into getResultSet");
}
return rs;
}
/**
* @return The preparedStatement (should be used in conjunction of
* createPreparedStatement)
*
* @throws WaarpDatabaseNoConnectionException
*/
public final PreparedStatement getPreparedStatement()
throws WaarpDatabaseNoConnectionException {
if (preparedStatement == null) {
throw new WaarpDatabaseNoConnectionException(
"SQL PreparedStatement is Null into getPreparedStatement");
}
return preparedStatement;
}
/**
* @return the dbSession
*/
public final DbSession getDbSession() {
return ls;
}
/**
* @return the isReady
*/
public final boolean isReady() {
return isReady;
}
/**
* @param isReady the isReady to set
*/
private void setReady(final boolean isReady) {
this.isReady = isReady;
}
@Override
public String toString() {
return request;
}
}