My開発メモ

トランザクション処理のパターンをメモ

try…with…resource文の場合、connはautocloseされるから、例外が発生した
場合、

conn.rollback();

を実行させることができない。(記述するタイミングがない)

そこで、もうひとつ内側に try…with…resource文を書いて、そこで
例外が発生した場合の処理を記述すればよい。

これは見た目があまりよくない。

もうひとつの方法としては、Connection の close()メソッドを
なんとかするというのはどうなんだろ?

Employee.java
package model;

import java.io.Serializable;

public class Employee implements Serializable {
	private String id;
	private String name;
	private int age;
	
	public Employee() {}
	public Employee(String id, String name, int age) {
		this.id = id;
		this.name = name;
		this.age = age;
	}

    // 略
}
DBConnect.java
package dao;

import java.sql.Connection;
import java.sql.DriverManager;
import java.sql.SQLException;

public class DBConnect {
  static final String JDBC_URL =
      "jdbc:h2:tcp://localhost/~/dbsample";
  static final String DB_USER = "sa";
  static final String DB_PASS = "";
  
  static Connection connect() throws SQLException {
    Connection conn = DriverManager.getConnection(
        JDBC_URL, DB_USER, DB_PASS);
    return conn;
  }
}
EmployeeDAO.java
package dao;

import java.sql.Connection;
import java.sql.PreparedStatement;
import java.sql.ResultSet;
import java.sql.SQLException;

import model.Employee;

public class EmployeeDAO {

  private String sql = "INSERT INTO employee (id, name, age) VALUES (?, ?, ?)";

  /**
   * トランザクション処理を入れたメソッド
   * @param emp
   * @return
   */
  public boolean create(Employee emp) {
    try (Connection conn = DBConnect.connect()) {
      conn.setAutoCommit(false);                 // <1>
      try (PreparedStatement pStmt =
                  conn.prepareStatement(sql);) { // <2>
        pStmt.setString(1, emp.getId());
        pStmt.setString(2, emp.getName());
        pStmt.setInt(3, emp.getAge());
        int result = pStmt.executeUpdate();
        if (result != 1) {
          conn.rollback();                      // <3>
          return false;
        }
      } catch (SQLException e) {
        conn.rollback();                        // <4>
        throw e;                                // <5>
      }
      conn.commit();                            // <6>
      conn.setAutoCommit(true);                 // <7>
    } catch (SQLException e) {
      e.printStackTrace();
      return false;
    }
    return true;
  }
}

<1> AutoCommit機能を解除
<2> 内側の try文
<3> 失敗しているのだから、ロールバックする必要ないのでは?
<4> 途中、例外が発生したのでロールバック。
<5> 例外を外側のcatch文に投げる。
<6> ここまでの処理を確定させる。
<7> AutoCommit機能をONにする。

参考

カテゴリー: Java, memo

タグ: commit, rollback, try-with-resource, トランザクション

カウント: 188