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

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



宮本@muimiです。

昼間質問させてもらった
トランザクションかけるクラスを簡単に作ってみました。

こういうクラスを利用すると、

・コネクションの閉め忘れはなくなります
・任意の例外を処理できます

でも、以下の例だと

・イチイチCommand作るのダルい
・普通にtry/catch/finallyでcommit/rollbackした方が見やすい

う〜ん、
もっといい方法はないものか。。。
ご意見、ご感想あれば聞かせてください。


※以下、コード。長くてすんまそん

==================================
DBCommand 
DBアクセス用コマンドインターフェイス
==================================
package db2;

import java.sql.*;

public interface DBCommand {

  /**
   * データベース操作を実行します
   * @return commitするときtrue
   */
  public boolean execute(Connection con) throws Exception;

}


==================================
TransactionMethod 
コマンドをもらって、トランザクションをかけるクラス
==================================
package db2;

import java.util.*;
import java.sql.*;


/**
 * トランザクションを必ずcommit or rollbackしてくれるクラス
 */
public class TransactionMethod {

  private boolean isCommitted;

  /**
   * データベースへのアクセスを実行します。
   */
  public void execute(DBCommand command) throws Exception{
    List commands = new ArrayList();
    commands.add(command);
    execute(commands);
  }

  /**
   * データベースへのアクセスを実行します(複数一括)
   */
  public void execute(List commands) throws Exception{

    isCommitted = false;
    Connection con;
    Statement smt;

    //Connectionの取得
    //ConnectionManagerは自作クラス
    try {
      con = ConnectionManager.getConnection();
      con.setAutoCommit(false);
    } catch (SQLException e) {
      throw new IllegalStateException(e.toString());
    }

    //トランザクション境界付操作
    try{
      boolean ok = true;
      for(int i=0; i<commands.size(); i++){
        DBCommand command = (DBCommand)commands.get(i);
        ok = command.execute(con);
        if(ok == false){
          break;
        }
      }

      if(ok){
        System.out.println("commit");
        con.commit();
        isCommitted = true;
      }

    }finally{

      if(con != null && !isCommitted){
        try{
          System.out.println("rollback");
          con.rollback();
        }catch(SQLException e){
          e.printStackTrace();
        }
      }
    }
  }
}



↑ここまで、
以降は補足


==================================
クライアント側
==================================
package db2;

import java.sql.*;
import java.util.*;

public class SomeLogic {

  public static void main(String[] args) throws Exception{

    new SomeLogic().doSomeBusiness();
  
  }


  public void doSomeBusiness(){
    TransactionMethod tm = new TransactionMethod();
    try {
      tm.execute(new SomeCommand());
    } catch (SQLException e){
      e.printStackTrace();
    } catch (Exception e) {
      e.printStackTrace();
    }
  }


  class SomeCommand implements DBCommand{

    private String title;

    public boolean execute(Connection con) throws Exception{

      CDEntity cd = CDEntity.create(con, title);
      cd.update(con);
      cd.delete(con);

      return true;
    }
  }


  class SelectCommand implements DBCommand{

    private String criteria;

    private List cds = new ArrayList();

    public SelectCommand(String criteria){
      this.criteria = criteria;
    }

    public boolean execute(Connection con) throws Exception{

      cds = CDEntity.selectByWhere(con, criteria);

      return true;
    }
    
    public List getResult(){
      return cds;
    }
  }

}


==================================
エンティティ(DAO?) 
もうちょっと簡単にはできる
==================================
package db2;

import java.sql.*;
import java.util.*;

public class CDEntity {
  private String title;
  private String artist;


  public static CDEntity create(Connection con, String title) throws 
SQLException{

    Statement smt = con.createStatement();
    smt.executeUpdate(
      "insert into cd(title) values("
      + "'" +title+ "'"
      + ")"
    );

    CDEntity cd = new CDEntity();
    cd.setTitle(title);
    return cd;
  }

  public void update(Connection con) throws SQLException{

    Statement smt = con.createStatement();
    smt.executeUpdate(
      "update cd "
      + "set artist = '" +artist+ "'"
      + "where title = '"+title+"'"
    );
  }

  public void delete(Connection con) throws SQLException{
    Statement smt = con.createStatement();
    smt.executeUpdate(
      "delete from cd "
      + "where title = '" +title+ "'"
    );
  }

  public static List selectByWhere(Connection con, String criteria) 
throws SQLException{

    List cds = new ArrayList();

    Statement smt = con.createStatement();
    ResultSet rs = smt.executeQuery(
      "select * from cd where " + criteria
    );

    while(rs.next()){
      CDEntity cd = new CDEntity();
      cd.setArtist(rs.getString("title"));
      cd.setTitle(rs.getString("artist"));
      cds.add(cd);
    }
      
    return cds;
  }



  /**
   * Returns the artist.
   * @return String
   */
  public String getArtist() {
    return artist;
  }

  /**
   * Returns the title.
   * @return String
   */
  public String getTitle() {
    return title;
  }

  /**
   * Sets the artist.
   * @param artist The artist to set
   */
  public void setArtist(String artist) {
    this.artist = artist;
  }

  /**
   * Sets the title.
   * @param title The title to set
   */
  public void setTitle(String title) {
    this.title = title;
  }

}


-------------------
宮本信二
mui@xxxxxxxxx
http://muimi.com/