質問をすることでしか得られない、回答やアドバイスがある。

15分調べてもわからないことは、質問しよう!

新規登録して質問してみよう
ただいま回答率
85.48%
MySQL

MySQL(マイエスキューエル)は、TCX DataKonsultAB社などが開発するRDBMS(リレーショナルデータベースの管理システム)です。世界で最も人気の高いシステムで、オープンソースで開発されています。MySQLデータベースサーバは、高速性と信頼性があり、Linux、UNIX、Windowsなどの複数のプラットフォームで動作することができます。

Java

Javaは、1995年にサン・マイクロシステムズが開発したプログラミング言語です。表記法はC言語に似ていますが、既存のプログラミング言語の短所を踏まえていちから設計されており、最初からオブジェクト指向性を備えてデザインされています。セキュリティ面が強力であることや、ネットワーク環境での利用に向いていることが特徴です。Javaで作られたソフトウェアは基本的にいかなるプラットフォームでも作動します。

MariaDB

MariaDBは、MySQL派生のオープンソースなリレーショナルデータベースシステムです。 また、MySQLとほぼ同じデータベースエンジンに対応しています。

Q&A

解決済

2回答

1386閲覧

javaでのmysqlのコミット・ロールバック

uer03108

総合スコア194

MySQL

MySQL(マイエスキューエル)は、TCX DataKonsultAB社などが開発するRDBMS(リレーショナルデータベースの管理システム)です。世界で最も人気の高いシステムで、オープンソースで開発されています。MySQLデータベースサーバは、高速性と信頼性があり、Linux、UNIX、Windowsなどの複数のプラットフォームで動作することができます。

Java

Javaは、1995年にサン・マイクロシステムズが開発したプログラミング言語です。表記法はC言語に似ていますが、既存のプログラミング言語の短所を踏まえていちから設計されており、最初からオブジェクト指向性を備えてデザインされています。セキュリティ面が強力であることや、ネットワーク環境での利用に向いていることが特徴です。Javaで作られたソフトウェアは基本的にいかなるプラットフォームでも作動します。

MariaDB

MariaDBは、MySQL派生のオープンソースなリレーショナルデータベースシステムです。 また、MySQLとほぼ同じデータベースエンジンに対応しています。

0グッド

0クリップ

投稿2017/09/17 14:39

編集2017/09/18 14:35

javaで、下記の様なmysql(mariaDb)のクラスを作りました。

コミットとロールバックも出来るようにしたつもりなのですが、これだと上手く動作しませんでした。
常にコミットになってしまいます。

構造に問題があるのでしょうか。
出来るだけ、db関係の変数はdbクラス内だけで処理できればと思って作りました。

mainクラス

public class Sample { public void main(){ String sql = ""; String url = "****"; String user = "****"; String pass = "****"; SampleDb sampleDb = new SampleDb(url, usr, pass); sampleDb.setCommit(); //コミット設定 sampleDb.execute(sql); //処理 //sampleDb.commit(); //コミット sampleDb.rollback(); //ロールバック } }

dbクラス

public class SampleDb { Connection con; Statement stmt; //コンストラクタ public SampleDb(String url, String user, String pass) { con = DriverManager.getConnection(url, user, pass); stmt = con.createStatement(); } //コミット設定 public void setCommit() throws SQLException{ con.setAutoCommit(false); } //コミット public void commit() throws SQLException{ con.commit(); } //ロールバック public void rollback() throws SQLException{ con.rollback(); } //クエリ実行 public boolean execute(String sql) throws SQLException{ boolean bl = stmt.execute(sql); return bl; } //クエリ実行(insert, update, delete) public int executeUpdate(String sql) throws SQLException{ int n = stmt.executeUpdate(sql); return n; } }

――――――――――――――――――――――――――――――――――
追記

回答有難うございました。
こちらの勘違いでした。insertではコミット・ロールバックともに動作致しました。
ですが、適当なテストテーブルを作成して、下記の様なクエリを実行すると必ずコミットになるようです。
回答者様の仰られた通りです。

//重複削除 sampleDb.setCommit(); sampleDb.execute("CREATE TEMPORARY TABLE tblTmp AS SELECT DISTINCT * FROM test"); sampleDb.executeUpdate("DELETE FROM test"); sampleDb.executeUpdate("INSERT INTO test SELECT * FROM tblTmp"); sampleDb.execute("DROP TABLE tblTmp"); sampleDb.commit(); //sampleDb.rollback();

――――――――――――――――――――――――――――――――――

追記の追記

クラスを使用しない場合でも、動作しない場合がありました。これって、仕様なのでしょうか。

String ip = "localhost"; String port = "3307"; String db = "sample"; String user = "****"; String pass = "****"; //接続 String url = "jdbc:mariadb://" + ip + ":" + port + "/" + db; Connection con = DriverManager.getConnection(url, user, pass); Statement stmt = con.createStatement(); // テーブル作成 stmt.execute("DROP TABLE IF EXISTS test"); stmt.execute("CREATE TABLE IF NOT EXISTS test (id int, name varchar(255))"); stmt.execute("INSERT INTO test (id, name) values (1, '日本語')"); //コミット/ロールバック con.setAutoCommit(false); stmt.execute("INSERT INTO test (id, name) values (2, '英語')"); stmt.execute("INSERT INTO test (id, name) values (2, '英語')"); //con.rollback(); //動作する con.commit(); //コミット/ロールバック con.setAutoCommit(false); stmt.execute("CREATE TEMPORARY TABLE tblTmp AS SELECT DISTINCT * FROM test"); stmt.executeUpdate("DELETE FROM test"); stmt.executeUpdate("INSERT INTO test SELECT * FROM tblTmp"); stmt.execute("DROP TABLE tblTmp"); con.rollback(); //動作しない //con.commit();

気になる質問をクリップする

クリップした質問は、後からいつでもMYページで確認できます。

またクリップした質問に回答があった際、通知やメールを受け取ることができます。

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

guest

回答2

0

ベストアンサー

幾つかコードが誤っているようです。このままではコンパイルが通りません。


コンパイルが通り、MySQLに接続できている前提でお話しします。
この例において、単一のDML(UPDATEやINSERT)を実行するだけであれば、意図した動作となると思います。
DMLとDDL(CREATE TABLE や ALTER TABLE)が混在したケースでは、ロールバックしたのにコミットされてしまうことがあります。

また、今回の質問とは無関係ですが、Statementをインスタンス変数として保持した場合、
StatementがCloseされなかったり、非同期アクセス時にトラブルを起こす原因となりますので、
あまりおすすめできません。

投稿2017/09/18 05:08

編集2017/09/18 05:15
mosa

総合スコア218

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

uer03108

2017/09/18 10:12

回答有難うございました。 >単一のDML(UPDATEやINSERT)を実行するだけであれば、意図した動作となると思います。 こちらでは、コミットにしかなりませんでした。 確認違いでしょうか。
mosa

2017/09/18 11:15

こちらで同じコードを書いてみたのですが、再現しませんね。。 以下の3点を教えてもらえますか? ・MySQL?MariaDB?のバージョン ・対象テーブルのストレージエンジン(下記SQLをMySQLで直接実行した結果のEngine列)    show table status LIKE '【対象のテーブル名】'; ・トランザクション分離レベル(下記SQLをMySQLで直接実行した結果)    show variables like 'tx_isolation';
uer03108

2017/09/18 14:41

お手数をお掛けして、申し訳ありません。 こちらの勘違いでした(追記参照)。 DMLとDDLを混在させる場合もあると思うのですが、クラスを使用しなくてもコミットにしかならない様です。 仕様なのでしょうか。
mosa

2017/09/19 00:46 編集

そうですね。MySQLの仕様です。 他のプログラムやMySQLコンソールから直接実行してもそうなります。 CREATE TABLE や DROP TABLE などのDDL文は「暗黙的なコミットを発生させるステートメント」と言われています。 https://dev.mysql.com/doc/refman/5.6/ja/implicit-commit.html
uer03108

2017/09/19 07:23

重ね重ね有難うございました。 仕様の中で、工夫しなさいと言うことですね。
guest

0

SQL例外がキャッチされていないのでコンパイルエラーが出るようですが、それはさておき、

接続URLやSQLが書かれていないためこちらでは判断しかねるところはありますが、例えば

java

1String url = "jdbc:mariadb://localhost:3306/test"; 2 3String sql = "insert into todo (`task`) values ('Javaから実行')";

などで実行した場合は特に問題なくロールバックされ、正常動作時は問題ありませんでした。
接続URLで自動コミットを設定されてる可能性があります。

投稿2017/09/18 12:23

A-pZ

総合スコア12011

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

uer03108

2017/09/18 14:42

回答有難うございました。 追記を参照願います。
guest

あなたの回答

tips

太字

斜体

打ち消し線

見出し

引用テキストの挿入

コードの挿入

リンクの挿入

リストの挿入

番号リストの挿入

表の挿入

水平線の挿入

プレビュー

15分調べてもわからないことは
teratailで質問しよう!

ただいまの回答率
85.48%

質問をまとめることで
思考を整理して素早く解決

テンプレート機能で
簡単に質問をまとめる

質問する

関連した質問