Mengapa transaksi diperlukan

Sangat sering, saat bekerja dengan database, situasi muncul ketika Anda perlu melakukan banyak tindakan berbeda, tetapi tindakan tersebut hanya masuk akal jika digabungkan.

Misalnya, kami sedang menulis perangkat lunak perbankan yang harus melakukan tiga hal:

  • Menarik uang dari rekening pelanggan
  • Tambahkan uang ke rekening penerima
  • Catat data postingan di “posting log”

Jika terjadi kesalahan selama pelaksanaan salah satu dari tindakan ini, maka dua tindakan lainnya juga harus dibatalkan. Tidak mungkin menghapus uang dari klien dan tidak menambahkannya ke penerima? Nah, atau menambah penerima, tetapi tidak menghapus dari klien?

Jadi, pengelompokan logis dari berbagai tindakan menjadi satu disebut transaksi . Dengan kata lain, transaksi adalah sekumpulan tindakan yang harus dilakukan secara bersama-sama . Jika ada tindakan yang gagal atau dijalankan dengan kesalahan, maka semua tindakan lainnya harus dibatalkan.

Sebuah transaksi biasanya memiliki tiga status:

  • keadaan awal - keadaan sistem sebelum menjalankan sekelompok tindakan
  • status sukses - status setelah grup tindakan selesai
  • keadaan gagal - ada yang tidak beres

Dalam hal ini, biasanya ada tiga perintah:

  • mulai/mulai - dieksekusi sebelum dimulainya kelompok tindakan logis
  • komit - dieksekusi setelah grup tindakan transaksi
  • rollback - memulai proses mengembalikan sistem dari keadaan gagal ke keadaan awal

Ia bekerja seperti ini.

Pertama, Anda perlu membuka transaksi - panggil metode begin() atau start() . Memanggil metode ini menunjukkan keadaan sistem yang akan kami coba kembalikan jika terjadi kesalahan.

Kemudian semua tindakan dilakukan, yang digabungkan menjadi grup logis - sebuah transaksi.

Kemudian metode commit() dipanggil . Panggilannya menandai akhir dari kelompok tindakan logis, dan juga biasanya memulai proses penerapan tindakan ini.

Ingat bagaimana kami menulis sesuatu di FileWriter: pertama, semua yang kami tulis disimpan di memori, dan kemudian ketika metode flush () dipanggil , semua data dari buffer di memori ditulis ke disk. Flush() ini adalah komit transaksi.

Nah, jika terjadi kesalahan selama pengoperasian transaksi, maka Anda perlu memulai proses kembali ke keadaan awal. Proses ini disebut rollback() , dan metode dengan nama yang sama biasanya bertanggung jawab untuk itu.

Secara kasar, ada 2 cara untuk menyelesaikan transaksi:

  • KOMIT - kami mengonfirmasi semua perubahan yang dilakukan
  • ROLLBACK - kembalikan semua perubahan yang dilakukan

Transaksi di JDBC

Hampir setiap DBMS dapat bekerja dengan transaksi. Jadi JDBC juga memiliki dukungan untuk kasus ini. Semuanya diimplementasikan dengan sangat sederhana.

Pertama, setiap panggilan ke metode execution() dari objek Pernyataan dieksekusi dalam transaksi terpisah. Untuk melakukannya, Connection memiliki parameter AutoCommit . Jika disetel ke true , maka commit() akan dipanggil setelah setiap panggilan ke metode execution() .

Kedua, jika Anda ingin mengeksekusi beberapa perintah dalam satu transaksi, maka Anda bisa melakukannya seperti ini:

  • nonaktifkan Komit Otomatis
  • memanggil tim kami
  • panggil metode commit() secara eksplisit

Ini terlihat sangat sederhana:

connection.setAutoCommit(false);

Statement statement = connection.createStatement();
int rowsCount1 = statement.executeUpdate("UPDATE  employee SET salary = salary+1000");
int rowsCount2 = statement.executeUpdate("UPDATE  employee SET salary = salary+1000");
int rowsCount3 = statement.executeUpdate("UPDATE  employee SET salary = salary+1000");

connection.commit();

Jika terjadi kesalahan pada server saat metode commit() sedang berjalan , maka SQL server akan membatalkan ketiga tindakan tersebut.

Tetapi ada situasi ketika kesalahan masih terjadi di sisi klien, dan kami tidak pernah melakukan pemanggilan metode commit() :

connection.setAutoCommit(false);

Statement statement = connection.createStatement();
int rowsCount1 = statement.executeUpdate("UPDATE  employee SET salary = salary+1000");
int rowsCount2 = statement.executeUpdate("UPDATE  employee SET salary = salary+1000");
int rowsCount3 = statement.executeUpdate("UPDATE multiple typos will result in an exception");

connection.commit();

Jika terjadi kesalahan selama eksekusi salah satu executionUpdate() , maka metode commit() tidak akan dipanggil. Untuk mengembalikan semua tindakan yang dilakukan, Anda perlu memanggil metode rollback() . Biasanya terlihat seperti ini:

try{
  	connection.setAutoCommit(false);

  	Statement statement = connection.createStatement();
  	int rowsCount1 = statement.executeUpdate("UPDATE  employee SET salary = salary+1000");
  	int rowsCount2 = statement.executeUpdate("UPDATE  employee SET salary = salary+1000");
  	int rowsCount3 = statement.executeUpdate("UPDATE multiple typos will result in an exception");

	  connection.commit();
 }
 catch (Exception e) {
   connection.rollback();
}

Savepoint

Dengan munculnya JDBC 3.0, menjadi mungkin untuk bekerja lebih efisien dengan rollback transaksi. Sekarang Anda dapat mengatur titik simpan - simpan titik, dan saat Anda memanggil operasi rollback () , putar kembali ke titik simpan tertentu.

Untuk menyimpan, Anda perlu membuat savepoint, ini dilakukan dengan perintah:

Savepoint save = connection.setSavepoint();

Mengembalikan ke savepoint dilakukan dengan perintah:

connection.rollback(save);

Mari coba tambahkan savepoint sebelum perintah kita yang bermasalah:

try{
  	connection.setAutoCommit(false);

  	Statement statement = connection.createStatement();
  	int rowsCount1 = statement.executeUpdate("UPDATE  employee SET salary = salary+1000");
  	int rowsCount2 = statement.executeUpdate("UPDATE  employee SET salary = salary+1000");

  	Savepoint save = connection.setSavepoint();
 	 try{
      	int rowsCount3 = statement.executeUpdate("UPDATE multiple typos will result in an exception");
 	 }
 	 catch (Exception e) {
    	   connection.rollback(save);
 	 }

	  connection.commit();
 }
 catch (Exception e) {
   connection.rollback();
}

Kami mengatur transaksi bersarang dengan menambahkan save-point sebelum memanggil metode yang bermasalah, dan kembali ke keadaan tersimpan dengan memanggil metode rollback(save) .

Ya, sangat mirip dengan save/load di game.