Mengapa urus niaga diperlukan

Selalunya, apabila bekerja dengan pangkalan data, situasi timbul apabila anda perlu melakukan banyak tindakan yang berbeza, tetapi ia hanya masuk akal bersama-sama.

Sebagai contoh, kami sedang menulis perisian perbankan yang harus melakukan tiga perkara:

  • Keluarkan wang dari akaun pelanggan
  • Tambahkan wang pada akaun penerima
  • Rekod data pengeposan dalam "log pengeposan"

Jika ralat berlaku semasa pelaksanaan mana-mana tindakan ini, maka dua yang lain juga mesti dibatalkan. Adalah mustahil untuk menghapuskan wang daripada pelanggan dan tidak menambahnya kepada penerima? Baik, atau tambahkan pada penerima, tetapi tidak dihapuskira daripada pelanggan?

Jadi, pengumpulan logik tindakan yang berbeza menjadi satu dipanggil transaksi . Dalam erti kata lain, urus niaga ialah sekumpulan tindakan yang mesti dilakukan bersama-sama sahaja . Jika sebarang tindakan gagal atau telah dilaksanakan dengan ralat, maka semua tindakan lain mesti dibatalkan.

Transaksi biasanya mempunyai tiga keadaan:

  • keadaan awal - keadaan sistem sebelum melaksanakan sekumpulan tindakan
  • keadaan kejayaan - nyatakan selepas kumpulan tindakan selesai
  • keadaan gagal - sesuatu telah berlaku

Dalam kes ini, biasanya terdapat tiga arahan:

  • mula/mula - dilaksanakan sebelum permulaan kumpulan tindakan logik
  • commit - dilaksanakan selepas kumpulan tindakan transaksi
  • rollback - memulakan proses mengembalikan sistem dari keadaan gagal ke keadaan awal

Ia berfungsi seperti ini.

Mula-mula anda perlu membuka transaksi - panggil kaedah begin() atau start() . Memanggil kaedah ini menunjukkan keadaan sistem yang akan kami cuba kembalikan jika berlaku masalah.

Kemudian semua tindakan dilakukan, yang digabungkan menjadi kumpulan logik - transaksi.

Kemudian kaedah commit() dipanggil . Panggilannya menandakan berakhirnya kumpulan tindakan yang logik, dan juga biasanya memulakan proses melaksanakan tindakan ini.

Ingat bagaimana kami menulis sesuatu dalam FileWriter: pertama, semua yang kami tulis disimpan dalam ingatan, dan kemudian apabila kaedah flush () dipanggil , semua data daripada penimbal dalam ingatan ditulis ke cakera. Flush() ini ialah komit transaksi.

Nah, jika ralat berlaku semasa operasi transaksi, maka anda perlu memulakan proses kembali ke keadaan permulaan. Proses ini dipanggil rollback() , dan kaedah dengan nama yang sama biasanya bertanggungjawab untuknya.

Secara kasarnya, terdapat 2 cara untuk menyelesaikan transaksi:

  • KOMIT - kami mengesahkan semua perubahan yang dibuat
  • ROLLBACK - gulung balik semua perubahan yang dibuat

Transaksi dalam JDBC

Hampir setiap DBMS boleh berfungsi dengan transaksi. Jadi JDBC juga mempunyai sokongan untuk kes ini. Semuanya dilaksanakan dengan sangat mudah.

Pertama, setiap panggilan ke kaedah execute() bagi objek Pernyataan dilaksanakan dalam transaksi berasingan. Untuk melakukan ini, Sambungan mempunyai parameter AutoCommit . Jika ia ditetapkan kepada true , maka commit() akan dipanggil selepas setiap panggilan ke kaedah execute() .

Kedua, jika anda ingin melaksanakan beberapa arahan dalam satu transaksi, maka anda boleh melakukannya seperti ini:

  • lumpuhkan Autocommit
  • memanggil perintah kami
  • panggil kaedah commit() secara eksplisit

Ia kelihatan sangat mudah:

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 ralat berlaku pada pelayan semasa kaedah commit() berjalan , maka pelayan SQL akan membatalkan ketiga-tiga tindakan.

Tetapi terdapat situasi apabila ralat masih berlaku pada sisi klien, dan kami tidak pernah mendapat panggilan kaedah 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 ralat berlaku semasa pelaksanaan satu executeUpdate() , maka kaedah commit() tidak akan dipanggil. Untuk melancarkan semula semua tindakan yang diambil, anda perlu memanggil kaedah rollback() . Ia biasanya kelihatan 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();
}

Savepoints

Dengan kemunculan JDBC 3.0, ia menjadi mungkin untuk berfungsi dengan lebih cekap dengan rollback transaksi. Kini anda boleh menetapkan titik simpan - simpan mata, dan apabila anda memanggil operasi rollback () , gulung semula ke titik simpan tertentu.

Untuk menyimpan, anda perlu membuat savepoint, ini dilakukan dengan arahan:

Savepoint save = connection.setSavepoint();

Berbalik ke savepoint dilakukan dengan arahan:

connection.rollback(save);

Mari cuba tambah titik simpan sebelum arahan bermasalah kami:

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 urus niaga bersarang dengan menambahkan titik simpan sebelum memanggil kaedah bermasalah dan kembali ke keadaan disimpan dengan memanggil kaedah rollback(simpan) .

Ya, ia sangat serupa dengan menyimpan/memuatkan dalam permainan.