All Downloads are FREE. Search and download functionalities are using the official Maven repository.

com.rapleaf.jack.BaseDatabaseConnection Maven / Gradle / Ivy

There is a newer version: 1.8
Show newest version
package com.rapleaf.jack;

import java.io.Closeable;
import java.io.IOException;
import java.io.Serializable;
import java.sql.Connection;
import java.sql.PreparedStatement;
import java.sql.SQLException;
import java.sql.Statement;

import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

public abstract class BaseDatabaseConnection implements Serializable, Closeable {

  private static Logger LOG = LoggerFactory.getLogger(BaseDatabaseConnection.class);

  public static String DISABLE_PROPERTY = "jack.db.disallow_connections";
  public static String DISABLE_ENV_VAR = "JACK_DB_DISALLOW_CONNECTIONS";


  protected transient Connection conn = null;

  /**
   * Get a Connection to a database.
   * If there is no connection, create a new one.
   */
  public Connection getConnection() {
    if (!isDisabled()) {
      return getConnectionInternal();
    } else {
      throw new RuntimeException("Tried to instantiate a connection even though connections have been disabled in this environment");
    }
  }

  protected abstract Connection getConnectionInternal();


  /**
   * Re-establish the connection in case it has been sitting idle for too
   * long and has been claimed by the server
   */
  public Connection resetConnection() {
    return resetConnection(null);
  }

  /**
   * Re-establish the connection in case it has been sitting idle for too
   * long and has been claimed by the server
   * This version specifies a cause and can be used when the reset is
   * performed as an attempt to recover from an exception
   */
  public Connection resetConnection(Throwable cause) {
    LOG.warn("Resetting database connection to attempt to recover from exception:", cause);
    if (conn != null) {
      try {
        if (!conn.getAutoCommit()) {
          conn = null;
          throw new RuntimeException("Cannot safely reset connection. May be in the middle of a transaction.", cause);
        }
        conn.close();
      } catch (SQLException e) {
        LOG.warn("Failed to reset database connection: {}", e);
      }
    }
    conn = null;
    return getConnection();
  }

  /**
   * Creates a connection using the argument credentials. Useful for when
   * MapReduce workers machines need to make database connections, as they
   * don't have access to the local config file. Returns true if the new
   * connection is made and false if a connection already exists.
   */
  public boolean connect() {
    if (conn == null) {
      conn = getConnection();
      return true;
    } else {
      return false;
    }
  }

  /**
   * Creates a Statement object that can be used to send SQL queries to the database.
   */
  public Statement getStatement() {
    try {
      return getConnection().createStatement();
    } catch (SQLException e) {
      throw new RuntimeException(e);
    }
  }

  /**
   * Creates a PreparedStatement object that can be used to send SQL queries to the database.
   */
  public PreparedStatement getPreparedStatement(String statement) {
    try {
      return getConnection().prepareStatement(statement);
    } catch (SQLException e) {
      throw new RuntimeException(e);
    }
  }

  public PreparedStatement getPreparedStatement(String statement, int options) {
    try {
      return getConnection().prepareStatement(statement, options);
    } catch (SQLException e) {
      throw new RuntimeException(e);
    }
  }

  public PreparedStatement getPreparedStatement(String statement, int resultSetType, int resultSetConcurrency) {
    try {
      return getConnection().prepareStatement(statement, resultSetType, resultSetConcurrency);
    } catch (SQLException e) {
      throw new RuntimeException(e);
    }
  }

  /**
   * Sets this connection's auto-commit mode to the given state. If a connection
   * is in auto-commit mode, then all its SQL statements will be executed and
   * committed as individual transactions. Otherwise, its SQL statements are
   * grouped into transactions that are terminated by a call to either the
   * method commit or the method rollback. By default, new connections are in
   * auto-commit mode.
   *
   * @param autoCommit
   */
  public void setAutoCommit(boolean autoCommit) {
    try {
      getConnection().setAutoCommit(autoCommit);
    } catch (SQLException e) {
      throw new RuntimeException(e);
    }
  }

  /**
   * Retrieves the current auto-commit mode
   */
  public boolean getAutoCommit() {
    try {
      return getConnection().getAutoCommit();
    } catch (SQLException e) {
      throw new RuntimeException(e);
    }
  }

  /**
   * Makes all changes made since the previous commit/rollback permanent and
   * releases any database locks currently held by this Connection object.
   * This method should be used only when auto-commit mode has been disabled.
   */
  public void commit() {
    try {
      getConnection().commit();
    } catch (SQLException e) {
      throw new RuntimeException(e);
    }
  }

  /**
   * Undoes all changes made in the current transaction and releases any
   * database locks currently held by this Connection object. This method should
   * be used only when auto-commit mode has been disabled.
   */
  public void rollback() {
    try {
      getConnection().rollback();
    } catch (SQLException e) {
      throw new RuntimeException(e);
    }
  }

  /**
   * Close the connection to the database.
   */
  @Override
  public void close() throws IOException {
    try {
      if (conn != null) {
        getConnection().close();
        conn = null;
      }
    } catch (SQLException e) {
      throw new IOException(e);
    }
  }

  private boolean isDisabled() {
    try {
      Boolean disabledBySystemProperty = false;
      try {
        disabledBySystemProperty = Boolean.parseBoolean(System.getProperty(DISABLE_PROPERTY));
      } catch (IllegalArgumentException e) {
        //property is not set
      }
      Boolean disabledByEnvVar = Boolean.parseBoolean(System.getenv(DISABLE_ENV_VAR));

      return disabledBySystemProperty || disabledByEnvVar;
    } catch (Exception e) {
      LOG.error("Encountered an error trying to determine disabled status: ", e); //migration safety code TODO remove
      return false;
    }
  }
}




© 2015 - 2025 Weber Informatics LLC | Privacy Policy