【Java】【MySQL】 Unique制約でエラーになった場合、リトライする

実装方法

https://dev.mysql.com/doc/refman/5.6/ja/error-messages-server.html
エラー: 1062 SQLSTATE: 23000 (ER_DUP_ENTRY)

メッセージ: '%s' はキー %d で重複しています

このエラーメッセージで返されるメッセージでは、ER_DUP_ENTRY_WITH_KEY_NAME の書式文字列が使用されます。

サンプルデータ

CREATE TABLE文

社員番号 emp_no がユニーク
CREATE TABLE `emp` (
	`id` BIGINT(20) NOT NULL AUTO_INCREMENT,
	`name` VARCHAR(100) NOT NULL,
	`birth_date` DATE NOT NULL,
	`emp_no` VARCHAR(20) UNIQUE,
	PRIMARY KEY (`id`)
)
ENGINE=InnoDB;

データ

以下のデータを入れておく
INSERT INTO emp(name, birth_date, emp_no)
    VALUES ('Mike', '1982-11-22', 'S0000-0001'),
           ('Tom', '1973-1-2', 'S0000-0002'),
           ('Smith', '1939-4-15', 'S0000-0003'),
           ('Ken', '1949-12-31', 'S0000-0004'),
           ('John', '1976-9-19', 'S0000-0005');

サンプル

import java.sql.Connection;
import java.sql.Date;
import java.sql.DriverManager;
import java.sql.PreparedStatement;

import com.mysql.jdbc.MysqlErrorNumbers;
import com.mysql.jdbc.exceptions.jdbc4.MySQLIntegrityConstraintViolationException;

public class SampleInsert {

  public static void main(String[] args) {
    try {
      System.out.println("Start");

      SampleInsert.dbAccess();
    } catch (Exception ex) {
      ex.printStackTrace();
    } finally {
      System.out.println("Finished");
    }
  }

  private static void dbAccess() throws Exception {
    int i = 1;
    while (true) {
      String name = "Kevin";
      Date birthDate = Date.valueOf("1973-1-2");
      String empNo = "S0000-000" + i;
      if (!insert(name, birthDate, empNo)) {
        System.out.println("Done " + i);
        break;
      }
      i++;
    }
  }

  private static boolean insert(String name, Date birthDate, String empNo) throws ClassNotFoundException {
    Class.forName("com.mysql.jdbc.Driver");

    try (
        Connection connection = DriverManager.getConnection(
            "jdbc:mysql://localhost:3306/sampledb", "root", "password");
        PreparedStatement statement = connection
            .prepareStatement("INSERT INTO emp(name, birth_date, emp_no) VALUES(?,?,?)");) {
      statement.setString(1, name);
      statement.setDate(2, birthDate);
      statement.setString(3, empNo);
      int number = statement.executeUpdate();
      System.out.println(number);
    } catch (MySQLIntegrityConstraintViolationException ex) {
      // ここでリトライ
      if (MysqlErrorNumbers.ER_DUP_ENTRY == ex.getErrorCode()) {
        System.out.println("Re-try");
        return true;
      }
      // 素通り
    } catch (Exception ex) {
      // 素通り
    }
    return false;
  }
}

出力結果

Start
Re-try
Re-try
Re-try
Re-try
Re-try
1
Done 6
Finished