トップ 一覧 置換 検索 ヘルプ RSS ログイン

JDBC操作クラスの変更点

  • 追加された行はこのように表示されます。
  • 削除された行はこのように表示されます。
!!!DBAccessor
JDBC経由でDBを操作するクラス
{{code Java,
import java.sql.*;
import java.util.ArrayList;
import java.util.HashMap;

/**
* DBにアクセスするためのクラス
*/
public class DBAccessor implements Cloneable {
  /** エラーをどこにも出力しない */
  final public static int TO_NO = 0;
  /** エラーをコンソールに出力する */
  final public static int TO_CONSOLE = 1;
  /** エラーをLogを使って出力する */
  final public static int TO_LOG = 2;
  /** エラーをDialogに出力する */
  final public static int TO_DIALOG = 3;
  
  /** データを読み込むモード */
  public static enum MODE {
    ALL, //全データを読み込む
    ONE  //1レコードだけ読み込む
  }
  
  /** エラー時にログの出力先 */
  protected int errorLog = TO_CONSOLE;
  
  /**  データベースコネクション */
  protected Connection con = null;
  /**  接続文字列(URL) */
  protected String connectionString = null;
  /**  ドライバ名 */
  protected String driverName = null;
  /**  パスワード */
  protected String pass = null;
  
  private static DBAccessor self = null;
  /**  ユーザ名 */
  protected String user = null;
  
  
  /**
  * コンストラクタ。
  *
  *@param  driverName        DBドライバ名
  *@param  connectionString  DB接続文字列(URL)
  *@param  user              ユーザー名
  *@param  pass              パスワード
  */
  public DBAccessor(String driverName, String connectionString, String user, String pass) {
    this(driverName, connectionString, user, pass, TO_CONSOLE);
  }
  
  /**
  * コンストラクタ。
  *
  *@param  driverName        DBドライバ名
  *@param  connectionString  DB接続文字列(URL)
  *@param  user              ユーザー名
  *@param  pass              パスワード
  *@param  errorLog          エラーの出力先。TO_NO、TO_CONSOLE、TO_LOG、TO_DIALOGのいずれか
  */
  public DBAccessor(String driverName, String connectionString, String user, String pass, int errorLog) {
    this.errorLog = errorLog;
    this.driverName = driverName;
    this.connectionString = connectionString;
    this.user = user;
    this.pass = pass;
    
    try {
      Class.forName(driverName);
    } catch (Exception e) {
      this.outputException(e);
    }
  }
  
  
  @Override
  public Object clone(){
    return new DBAccessor(
      this.driverName,
      this.connectionString,
      this.user,
      this.pass,
      this.errorLog);
  }

  
  
  /**  接続を閉じる */
  public void close() {
    if (!isClosed()) {
      try {
        con.close();
      } catch (Exception e) {
        this.outputException(e);
      }
      con = null;
    }
  }
  
  /**
  * データベースに接続し、SQL 文をデータベースに送るための Statement オブジェクトを生成します。
  *
  *@return    新しいデフォルト Statement オブジェクト
  *@exception  SQLException  データベースアクセスエラーが発生した場合、このメソッドがクローズされた接続に対して呼び出された場合、または指定されたパラメータが型および並行処理を示す ResultSet 定数でない場合 
  */
  public Statement createStatement() throws SQLException{
    if (connect()){
      return con.createStatement();
    }
    return null;
  }
  
  /**
  * データベースに接続し、パラメータ付き SQL 文をデータベースに送るための PreparedStatement オブジェクトを生成します。  
  *
  *@param  sql  1 つ以上の '?' IN パラメータプレースホルダーを含めることができる SQL 文 
  *@return    プリコンパイルされた SQL 文を含む新しいデフォルトの PreparedStatement オブジェクト 
  *@exception  SQLException  データベースアクセスエラーが発生した場合、またはこのメソッドがクローズされた接続について呼び出された場合 
  */
  public PreparedStatement prepareStatement(String sql) throws SQLException {
    if (connect()){
      return con.prepareStatement(sql);
    }
    return null;
  }
  
  /**
  * データベースのストアドプロシージャーを呼び出すための CallableStatement オブジェクトを生成します
  *
  *@param  sql - 1 つ以上の '?' パラメータプレースホルダーを含めることができる SQL 文。 通常この文は、JBDC 呼び出しのエスケープ構文を使用して指定される
  *@return    プリコンパイルされた SQL 文を含む新しいデフォルトの CallableStatement オブジェクト
  *@exception  SQLException  データベースアクセスエラーが発生した場合、またはこのメソッドがクローズされた接続について呼び出された場合 
  */
  public CallableStatement prepareCall(String sql) throws SQLException {
    if (connect()){
      return con.prepareCall(sql);
    }
    return null;
  }
  
  /**
  * 指定された Statmentクラス インスタンスを解放します。  
  *
  *@param  st  Statmentクラス インスタンス
  */
  public void close(Statement st){
    if (st != null){
      try {
        st.close();
      } catch (Exception e){
        this.outputException(e);
      }
    }
  }
  
  /**
  * 指定された ResultSetクラス インスタンスを解放します。  
  *
  *@param  rs  ResultSetクラス インスタンス
  */
  public void close(ResultSet rs){
    if (rs != null){
      try {
        rs.close();
      } catch (Exception e){
        this.outputException(e);
      }
    }
  }
  
  /**
  * 指定された Statmentクラス インスタンス と ResultSetクラス インスタンス を解放します。  
  *
  *@param  st  Statmentクラス インスタンス
  *@param  rs  ResultSetクラス インスタンス
  */
  public void close(Statement st, ResultSet rs){
    close(rs);
    close(st);
  }
  
  /**
  * コミット処理をする
  *
  *@return    コミット処理に成功した場合はTrue、それ以外はFalse。
  */
  public boolean commit() {
    if (isClosed()) {
      return false;
    }
    
    try {
      con.commit();
      return true;
    } catch (Exception e) {
      this.outputException(e);
      return false;
    }
  }
  
  
  
  /**
  *  データベース接続
  *
  *@return    接続に成功した場合はTrue、それ以外はFalse。
  */
  public boolean connect() throws SQLException{
    boolean result = false;
    if (isClosed()) {
      con = DriverManager.getConnection(connectionString,
        user, pass);
      con.setAutoCommit(false);
      result = true;
    } else {
      // Log.getLogger().severe("既に接続されています");
      result = true;
    }
    return result;
  }
  
  
  /**
  *  指定されたパラメータからDBAccessorインスタンスを返す。
  *  getInstance() を使用することにより、生成された
  *  インスタンスを取り出すことが出来る。<br><br>
  *  もし、以前に生成されたインスタンスがあれば接続を閉じる。
  *
  *@param  driverName        DBドライバ名
  *@param  connectionString  DB接続文字列(URL)
  *@param  user              ユーザー名
  *@param  pass              パスワード
  *@return                   生成したDBAccessorのインスタンス
  */
  public static DBAccessor createInstance(String driverName, String connectionString, String user, String pass) {
    return createInstance(driverName, connectionString, user, pass, TO_CONSOLE);
  }
  
  /**
  *  指定されたパラメータからDBAccessorインスタンスを返す。
  *  getInstance() を使用することにより、生成された
  *  インスタンスを取り出すことが出来る。<br><br>
  *  もし、以前に生成されたインスタンスがあれば接続を閉じる。
  *
  *@param  driverName        DBドライバ名
  *@param  connectionString  DB接続文字列(URL)
  *@param  user              ユーザー名
  *@param  pass              パスワード
  *@param  errorLog          エラーの出力先。TO_NO、TO_CONSOLE、TO_LOG、TO_DIALOGのいずれか
  *@return                   生成したDBAccessorのインスタンス
  */
  public static DBAccessor createInstance(String driverName, String connectionString, String user, String pass, int errorLog) {
    if (self != null && !self.isClosed()){
      self.close();
    }
    self = new DBAccessor(driverName, connectionString, user, pass, errorLog);
    return getInstance();
  }
  
  
  
  /**
  *  createInstance()メソッドによって生成されたインスタンスを
  *  取得する。
  *
  *@return    createInstanceによって生成されたDBAccessorインスタンス
  */
  public static DBAccessor getInstance() {
    return self;
  }
  
  
  /**
  *  createInstance()メソッドによって生成されたインスタンスから
  *  新しいDBAccessorを返す
  *
  *@return    createInstanceによって生成されたDBAccessorインスタンスから
  *           生成された新しいDBAccessor
  */
  public static DBAccessor newInstance() {
    return (DBAccessor)getInstance().clone();
  }
  
  
  /**
  *  接続状態を返す。
  *
  *@return    閉じている場合はTrue。
  */
  public boolean isClosed() {
    try {
      return (con == null || con.isClosed());
    } catch (Exception e) {
      this.outputException(e);
      return true;
    }
    
  }
  
  
  /**
  * ロールバック処理をする
  *
  *@return    Description of the Return Value
  */
  public boolean rollback() {
    if (isClosed()) {
      return false;
    }
    
    try {
      con.rollback();
      return true;
    } catch (Exception e) {
      this.outputException(e);
      return false;
    }
  }
  
  /**
  * 指定された Exceptionクラス インスタンスよりエラーを出力します。
  *
  *@param  e  Exceptionクラス インスタンス
  */
  private void outputException(Exception e){
    switch (errorLog) {
    case TO_LOG:
      //Log.logStackTrace(e);
      break;
    case TO_CONSOLE:
      System.out.println(e);
      break;
    case TO_NO:
      break;
    case TO_DIALOG:
      javax.swing.JOptionPane.showMessageDialog(null, e);
      break;
    }
  }
  
  /**
  * 指定されたエラーの出力先をセットします。
  *
  *@param  errorLog  エラーの出力先。TO_NO、TO_CONSOLE、TO_LOG、TO_DIALOGのいずれか
  */
  public void setErrorLog(int errorLog){
    this.errorLog = errorLog;
  }
  
  /**
  * データベースのコネクションを返します。 
  * 
  *@return    データベースコネクション
  */
  public Connection getConnection() throws SQLException{
    if (connect()){
      return con;
    }
    return null;
  }
  
  /**
  * パラメータの型に合わせて PreparedStatement にパラメータをセットする。
  * 
  *@param  st             PreparedStatementインスタンス
  *@param  param          パラメータのArrayList
  *@exception  Exception  処理中に発生した例外
  */
  public void setParameters(PreparedStatement st, ArrayList<Object> param) throws Exception {
    setParameters(st, param.toArray());
  }
  
  /**
  * パラメータの型に合わせて PreparedStatement にパラメータをセットする。
  * 
  *@param  st             PreparedStatementインスタンス
  *@param  param          パラメータのObject配列
  *@exception  Exception  処理中に発生した例外
  */
  public void setParameters(PreparedStatement st, Object[] param) throws Exception {
    for (int i = 0; i < param.length; i++) {
      if (param[i] instanceof Long){
        st.setLong(i + 1, (Long)param[i]);
      } else if (param[i] instanceof Double){
        st.setDouble(i + 1, (Double)param[i]);
      } else if (param[i] instanceof Integer){
        st.setInt(i + 1, (Integer)param[i]);
      } else if (param[i] instanceof java.sql.Date){
        st.setDate(i + 1, (java.sql.Date)param[i]);
      } else {
        st.setString(i + 1, (String)param[i]);
      }
    }
  }
  
  /** 
  * 指定されたSQLを実行し、実行結果を ArrayList で返す。
  * 
  * @param sql 実行する SQL文
  * @param mode 戻り値のモード。ALL の場合は全件、ONE の場合は最初の1件を返す。
  */
  public ArrayList<HashMap> executeQuery(String sql, MODE mode) throws Exception {
    if (!connect()){
      return null;
    }
    
    PreparedStatement st = con.prepareStatement(sql);
    ArrayList<Object> args = new ArrayList<Object>();
    return executeQuery(st,args, mode);
  }
  
  /** 
  * 指定された PreparedStatement を実行し、実行結果を ArrayList で返す。
  * 
  * @param st 実行する PreparedStatement
  * @param args PreparedStatement の引数。必要ない場合は null。 
  * @param mode 戻り値のモード。ALL の場合は全件、ONE の場合は最初の1件を返す。
  */
  public ArrayList<HashMap> executeQuery(PreparedStatement st, ArrayList<Object> args, MODE mode) throws Exception {
    ResultSet rs = null;
    ArrayList<HashMap> rows = null;
    
    try {
      if (args == null){
        args = new ArrayList<Object>();
      }
      
      
      ResultSetMetaData rsmd = null;
      setParameters(st,args);
      
      rs = st.executeQuery();
      rsmd = rs.getMetaData();
      
      int colCnt = rsmd.getColumnCount();
      String colLabel = "";
      rows = new ArrayList<HashMap>();
      while(rs.next()){
        HashMap<Object,Object> row = new HashMap<Object,Object>();
        for (int i = 0; i < colCnt; i++){
          colLabel = rsmd.getColumnLabel(i+1);
          row.put(colLabel,rs.getObject(colLabel));
        }
        rows.add(row);
        
        if (mode == MODE.ONE){
          break;
        }
      }
      return rows;
    } finally {
      close(st,rs);
    }
  }
}

}}

!!!DBPoolManager 
DBAccessorをプールするクラス。
{{code Java,
import java.util.*;

public class DBPoolManager {
  /**  接続文字列(URL) */
  private String connectionString = null;
  /**  ドライバ名 */
  private String driverName = null;
  /**  パスワード */
  private String pass = null;
  /**  ユーザ名 */
  private String user = null;
  /** エラー時にログの出力先 */
  protected int errorLog = DBAccessor.TO_CONSOLE;
  
  /** ロックオブジェクト */
  private byte[] lock = new byte[0];
  /** プール */
  private HashStack<DBAccessor> pool;
  /** 管理しているすべてのオブジェクト  */
  private HashSet<DBAccessor> allList;
  /** 自動クローズ処理用タイマー */
  private Timer closeTimer;
  /** 最後に使用されてから自動クローズするまでの時間 */
  private long closeTime;
  /** 最後に使用されてから自動クローズするまでの時間 のデフォルト値 */
  final static private long DEFAULT_DELAY = 1000 * 60 * 60;
  /** 自分自身のオブジェクト */
  private static DBPoolManager self = null;
  
  
  /**
  * コンストラクタ。
  *
  *@param  driverName        DBドライバ名
  *@param  connectionString  DB接続文字列(URL)
  *@param  user              ユーザー名
  *@param  pass              パスワード
  */
  public DBPoolManager(String driverName, String connectionString, String user, String pass, int poolSize) {
    this(driverName, connectionString, user, pass, DBAccessor.TO_CONSOLE,poolSize);
  }
  
  
  /**
  * コンストラクタ。
  *
  *@param  driverName        DBドライバ名
  *@param  connectionString  DB接続文字列(URL)
  *@param  user              ユーザー名
  *@param  pass              パスワード
  *@param  errorLog          エラーの出力先。TO_NO、TO_CONSOLE、TO_LOG、TO_DIALOGのいずれか
  *@param  poolSize          プールのサイズ
  */
  public DBPoolManager(String driverName, String connectionString, String user, String pass, int errorLog, int poolSize) {
    this(driverName, connectionString, user, pass, DBAccessor.TO_CONSOLE,poolSize, DEFAULT_DELAY);
  }
  
  
  /**
  * コンストラクタ。
  *
  *@param  driverName        DBドライバ名
  *@param  connectionString  DB接続文字列(URL)
  *@param  user              ユーザー名
  *@param  pass              パスワード
  *@param  errorLog          エラーの出力先。TO_NO、TO_CONSOLE、TO_LOG、TO_DIALOGのいずれか
  *@param  poolSize          プールのサイズ
  *@param  closeTime        使用していないコネクションを閉じるまでの時間(ミリ秒)
  */
  public DBPoolManager(String driverName, String connectionString, String user, String pass, int errorLog, int poolSize, long closeTime) {
    
    this.driverName = driverName;
    this.connectionString = connectionString;
    this.user = user;
    this.pass = pass;
    this.errorLog = errorLog;
    this.closeTime = closeTime;
    
    if (poolSize < 1){
      poolSize = 10;
    }
    pool = new HashStack<DBAccessor>();
    for(int i = 0; i < poolSize; i++){
      pool.push(null);
    }
    allList = new HashSet<DBAccessor>();
    startTimer(closeTime / 10);
  }
  
  
  /**
  * プールされているコネクションを自動的に
  * クローズするためのタイマーを開始する
  * 
  *@param  delay  コネクションを自動的に閉じるまでの時間
  */
  public void startTimer(long delay){
    if (this.closeTimer != null){
      stopTimer();
    }
    this.closeTimer = new Timer();
    TimerTask task = new TimerTask(){
      @Override
      public void run(){
        closeNotUsed();
      }
    };
    this.closeTimer.schedule(task, delay, delay);
  }
  
  
  /**
  * プールされているコネクションを自動的に
  * クローズするためのタイマーを止める 
  */
  public void stopTimer(){
    if (this.closeTimer != null){
      this.closeTimer.cancel();
      this.closeTimer = null;
    }
  }
  
  
  /**
  * 管理しているコネクションをすべて閉じて、
  * メモリを開放する 
  */
  public void dispose(){
    closeAll();
    stopTimer();
  }
  
  
  /**
  *  指定されたパラメータからDBAccessorインスタンスを返す。
  *  getInstance() を使用することにより、生成された
  *  インスタンスを取り出すことが出来る。<br><br>
  *
  *@param  driverName        DBドライバ名
  *@param  connectionString  DB接続文字列(URL)
  *@param  user              ユーザー名
  *@param  pass              パスワード
  *@param  poolSize          プールのサイズ
  */
  public static DBPoolManager createInstance(String driverName, String connectionString, String user, String pass, int poolSize) {
    return createInstance(driverName, connectionString, user, pass, DBAccessor.TO_CONSOLE, poolSize);
  }
  
  
  /**
  *  指定されたパラメータからDBAccessorインスタンスを返す。
  *  getInstance() を使用することにより、生成された
  *  インスタンスを取り出すことが出来る。<br><br>
  *
  *@param  driverName        DBドライバ名
  *@param  connectionString  DB接続文字列(URL)
  *@param  user              ユーザー名
  *@param  pass              パスワード
  *@param  errorLog          エラーの出力先。TO_NO、TO_CONSOLE、TO_LOG、TO_DIALOGのいずれか
  *@param  poolSize          プールのサイズ
  */
  public static DBPoolManager createInstance(String driverName, String connectionString, String user, String pass, int errorLog, int poolSize) {
    return createInstance(driverName, connectionString, user, pass, DBAccessor.TO_CONSOLE, poolSize, DEFAULT_DELAY);
  }
  
  
  /**
  *  指定されたパラメータからDBAccessorインスタンスを返す。
  *  getInstance() を使用することにより、生成された
  *  インスタンスを取り出すことが出来る。<br><br>
  *
  *@param  driverName        DBドライバ名
  *@param  connectionString  DB接続文字列(URL)
  *@param  user              ユーザー名
  *@param  pass              パスワード
  *@param  errorLog          エラーの出力先。TO_NO、TO_CONSOLE、TO_LOG、TO_DIALOGのいずれか
  *@param  poolSize          プールのサイズ
  *@param  closeTime        使用していないコネクションを閉じるまでの時間(ミリ秒)
  */
  public static DBPoolManager createInstance(String driverName, String connectionString, String user, String pass, int errorLog, int poolSize, long closeTime) {
    if (self != null){
      self.dispose();
    }
    self = new DBPoolManager(
      driverName,
      connectionString,
      user,
      pass,
      errorLog,
      poolSize,
      closeTime);
    return getInstance();
  }
  
  
  /**
  *  createInstance()メソッドによって生成されたインスタンスを
  *  取得する。
  *
  *@return    createInstanceによって生成された DBPoolManager インスタンス
  */
  public static DBPoolManager getInstance() {
    return self;
  }
  
  
  /**
  * DBAccessor を返す。 
  * 
  *@return    DBAccessor
  */
  public DBAccessor getDBAccessor(){
    synchronized(lock){
      // System.out.println("get " + Thread.currentThread());
      while(pool.empty()){
        try {
          // System.out.println("lock " + Thread.currentThread());
          lock.wait();
        } catch (Exception e){
        }
      }
      // System.out.println("get2 " + Thread.currentThread());
      DBAccessor db = pool.pop();
      if (db == null){
        db = new DBAccessorForPool(
          this,
          driverName,
          connectionString,
          user,
          pass,
          errorLog
          );
        allList.add(db);
      }
      return db;
    }
  }
  
  
  /**
  * DBAccessor をプールへ戻す 
  * 
  *@param  db  プールへ戻す DBAccessor
  */
  private void pushDBAccessor(DBAccessor db){
    synchronized(lock){
      // System.out.println("push " + Thread.currentThread());
      if (allList.contains(db) && !pool.contains(db)){
        pool.push(db);
        // System.out.println("notify " + Thread.currentThread());
        lock.notify();
      }
    }
  }
  
  
  /**
  * 管理しているコネクションをすべて閉じる 
  * 
  */
  private void closeAll(){
    for(DBAccessor db : allList){
      if (db instanceof DBAccessorForPool){
        ((DBAccessorForPool)db).closeConnection();
      } else {
        db.close();
      }
    }
  }
  
  
  /**
  * 使用されていないコネクションを閉じる 
  * 
  */
  private void closeNotUsed(){
    synchronized(lock){
      Iterator<DBAccessor> iterator = pool.iterator();
      long nowTime = System.currentTimeMillis();
      
      while(iterator.hasNext()){
        DBAccessor dba = iterator.next();
        if (dba != null && !dba.isClosed() && dba instanceof DBAccessorForPool){
          DBAccessorForPool dbafp = (DBAccessorForPool)dba;
          long lastUseTime = dbafp.getLastUseTime();
          if ( nowTime - lastUseTime > closeTime ){
            dbafp.closeConnection();
          }
        }
      }
    }
  }
  
  
  
  static class HashStack<T> {
    private HashSet<T> set;
    private Stack<T> stack;
    
    public HashStack(){
      set = new HashSet<T>();
      stack = new Stack<T>();
    }
    
    public void push(T t){
      set.add(t);
      stack.push(t);
    }
    
    public T pop(){
      T t = stack.pop();
      set.remove(t);
      return t;
    }
    
    public int size(){
      return set.size();
    }
    
    public Iterator<T> iterator() {
      return set.iterator();
    }
    
    public boolean contains(T t){
      return set.contains(t);
    }
    
    public boolean empty(){
      return stack.empty();
    }
  }
  
  
  
  static class DBAccessorForPool extends DBAccessor {
    private DBPoolManager manager;
    private long lastUseTime;
    
    /**
    * コンストラクタ。
    *
    *@param  driverName        DBドライバ名
    *@param  connectionString  DB接続文字列(URL)
    *@param  user              ユーザー名
    *@param  pass              パスワード
    *@param  errorLog          エラーの出力先。TO_NO、TO_CONSOLE、TO_LOG、TO_DIALOGのいずれか
    */
    public DBAccessorForPool(DBPoolManager manager, String driverName, String connectionString, String user, String pass, int errorLog) {
      super(driverName, connectionString, user, pass, DBAccessor.TO_CONSOLE);
      this.manager = manager;
      this.lastUseTime = System.currentTimeMillis();
    }
    
    private void closeConnection(){
      super.close();
    }
    
    @Override
    public void close(){
      rollback();
      this.lastUseTime = System.currentTimeMillis();
      manager.pushDBAccessor(this);
    }
    
    public long getLastUseTime(){
      return lastUseTime;
    }
  }
}
}}
{{category2 プログラミング言語,Java}}