[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

[jfriends-ml 10541] Re: DB トランザク ション (度々 commit/rollback を書きたくない)



門脇です。

#今更ですけど。

私が時々使うのは,例えばこんな感じのものです。

で,DbRequest interface を実装するのは,新しいクラスでも良いし,
クライアントクラスが直接実装して,

  result = executor.executeQuery(this);

しても良い,っつーいいかげんな感じです(状況に応じて良きにはから
う,と)。
なので,this 渡しで良いのなら Command クラスを別途作る必要は無い
です。

こんなデザインを使うのは

・DBの例外処理が面倒(毎回同じコードを書くのが面倒い)
  -> 宮本さんと同じですね

・DB検索用の select 文と,その抽出結果からの値オブジェクトの生成
  用コードは大体1対1に対応する。ので,まとめて一箇所に書いておき
  たい。

からですが,JDO とかのデータバインディングフレームワークを使うの
が本道でしょうね。
#勉強しないと。(^^;

まあ,お気軽お手軽な方法として,参考にでもなれば幸いですし,もっ
と簡単かつ有効な方法を実践されている方は,ぜひとも教えてください
ませ。



// DB処理要求インターフェース
public interface DbRequest {
  public String getSql();
  public Object parseResultSet(ResultSet rs);
}


// DB処理実行クラス
public class DbExecutor {
  private ConnectionManager cnnManager; // コネクションプール用
  private Connection cnn; // コネクション
  private boolean state;  // トランザクション管理用

  public DbExecuter(ConnectionManager cnnManager) {
    this.cnnManager = cnnManager;
    cnn = cnnManager.getConnection();
    cnn.setAutoCommit(false);
    state = true;
  }

  public Object executeQuery(DbRequest request) {
    if (! state)
      throw new IllegalStateException("前のクエリに失敗してるで");
    Statement statement = cnn.createStatement();
    try {
      String sql = request.getSql();
      ResultSet rs = statement.executeQuery(sql);
      try {
	return request.parseRecordSet(rs);
      } finally {
	rs.close();
      }
    } catch(SQLException e) {
      e.printStackTrace();
      state = false;
      return null;
    } catch(Exception e) {
      e.printStackTrace();
      state = false;
      throw e;
    } finally {
      statement.close();
    }
  }

  public int executeUpdate(DbRequest request) {
    if (! state)
      throw new IllegalStateException("前のクエリに失敗してるで");
    Statement statement = cnn.createStatement();
    try {
      String sql = request.getSql();
      return statement.executeUpdate(sql);
    } catch(SQLException e) {
      e.printStackTrace();
      state = false;
      return -1;
    } catch(Exception e) {
      e.printStackTrace();
      state = false;
      throw e;
    } finally {
      statement.close();
    }
  }

  public void close() {
    try {
      if (state) {
	cnn.commit();
      } else {
	cnn.rollback();
      }
    } catch(SQLException e) {
      e.printStackTrace();
    } finally {
      cnnManager.releaseConnection(cnn);
    }
  }
}


// 実際のDB処理要求クラス(の一つ)
public ADbRequest implements DbRequest {

  public String getSql() {
    return "select .....";
  }

  public Object parseRecordSet(RecordSet rs) {
    List list = new ArrayList();
    while (rs.next()) {
      list.add(new Hoge(rs.getInt(0), rs.getString(1)));
    }
    return list;
  }
}


// 利用例というか
public AClient() {
  ...
  public void someMethod() {

    List result;
    DbRequest request = new ADbRequest(some, parameters);
    DbExecutor executor = new DbExecutor(cnnManager);
    try {
      result = (List) executor.executeQuery(request);
    } finally {
      executor.close();
    }
    ....
  }
}
-- 
門脇 太郎