JavaRush /Курсы /All lectures for GE purposes /ტრანზაქციები ბაზასთან მუშაობისას

ტრანზაქციები ბაზასთან მუშაობისას

All lectures for GE purposes
1 уровень , 256 лекция
Открыта

რატომ გვჭირდება ტრანზაქციები

ძალიან ხშირად, როდესაც ბაზასთან მუშაობას იწყებთ, წარმოიქმნება სიტუაცია, როცა საჭიროა ბევრი განსხვავებული მოქმედების შესრულება, რომელთა მნიშვნელობა მხოლოდ ერთად ყოფნისას არსებობს.

მაგალითად, ვწერთ საბანკო პროგრამას, რომელიც უნდა გააკეთოს სამი რამ:

  • ფულის ჩამოწერა კლიენტის ანგარიშიდან
  • ფულის დამატება მიმღების ანგარიშზე
  • მონაცემების ჩაწერა "ჟურნალ პრვოდოკში"

თუ ამ მოქმედებების შესრულებისას რომელიმე შეცდომა მოხდება, დანარჩენი ორი უნდა გავაუქმოთ კიდეც. ხომ არ შეიძლება კლიენტის ფული ჩამოვწეროთ და არ დავამატოთ მიმღებს? ან დავამატოთ მიმღებს, მაგრამ არ ჩამოვწეროთ კლიენტს?

აი, ასეთი ლოგიკური ჯგუფის შექმნა სხვადასხვა მოქმედებების ერთში ეწოდება ტრანზაქცია. ანუ, ტრანზაქცია არის მოქმედებების ჯგუფი, რომლებიც უნდა შესრულდნენ მხოლოდ ყველა ერთად. თუ რომელიმე მოქმედება არ შესრულდა ან შესრულდა შეცდომით, მაშინ დანარჩენი მოქმედებები უნდა გაუქმდეს.

ტრანზაქციას ჩვეულებრივ სამი მდგომარეობა აქვს:

  • initial state — სისტემის მდგომარეობა მოქმედებების ჯგუფის შესრულების წინ
  • success state — მდგომარეობა მოქმედებების ჯგუფის დასრულების შემდეგ
  • failed state — რაღაც ისე ვერ წავიდა

ამასთანავე, ძირითადად სამი ბრძანებაა:

  • begin/start — გადის ლოგიკური მოქმედებების ჯგუფამდე
  • commit — შესრულების შემდეგ
  • rollback — აძლევთ საშუალებას სისტემას დაბრუნდეს failed state-დან initial state-ში

ეს მუშაობს ასე.

თავდაპირველად თქვენ უნდა გახსნათ ტრანზაქცია — გამოიწვიოთ მეთოდი begin() ან start(). ამ მეთოდის გამოძახების შემდეგ ვცდილობთ, რომ სისტემური მდგომარეობა, რომელშიც ვცდილობთ დაბრუნებას, თუ რამე არასწორედ წავა.

შემდეგ სრულდება ყველა მოქმედება, რომლებიც ლოგიკურ ჯგუფში არიან გაწელილი — ტრანზაქცია.

შემდეგ გამოიწვიოდით მეთოდი commit(). მისი გამოძახება აღნიშნავს ლოგიკური მოქმედებების ჯგუფის დასრულებას, ასევე, როგორც წესი, იწყება მოქმედებების განხორციელების პროცესი.

მახსოვს, როდესაც რაღაც FileWriter-ში ვწერდით: თავდაპირველად ყველაფერი, რაც დავწერეთ, მეხსიერებაში ინახება, შემდეგ, როდესაც გამოვიძახებდით მეთოდს flush(), ყველა მონაცემი მეხსიერების ბუფერში იწერება დისკზე. ეს flush() სწორედ ტრანზაქციის კომიტია.

და თუ ტრანზაქციის შესრულებაზე შეფერხება მოხდა, საჭიროა დაბრუნების პროცესის ინიცირება საწყის მდგომარეობაში. ამ პროცესს ეწოდება rollback(), და ამისთვის, როგორც წესი, პასუხისმგებელია შესაბამისი მეთოდი.

მოკლედ, ტრანზაქციის დასრულების ორი გზა არსებობს:

  • COMMIT — ვადასტურებთ ყველა გაკეთებულ ცვლილებას
  • ROLLBACK — ვაბრუნებთ ყველა გაკეთებულ ცვლილებას

ტრანზაქციები JDBC-ში

პრაქტიკულად ყველა სუბედბმც დებს ტრანზაქციების მხარდაჭერას. ასე რომ, JDBC-შიც ეს ფუნქცია არსებობს. ყველაფერი ძალიან მარტივად არის რეალიზებული.

ჯერ ერთი, ყოველი მეთოდის execute() გამოძახება Statement ობიექტზე ხდება ცალკეულ ტრანზაქციაში. ამისთვის Connection-ს აქვს პარამეტრი AutoCommit. თუ ის true-შია, მაშინ commit() გამოძახება ხდება ყოველი მეთოდის execute() გამოძახების შემდეგ.

მეორეს მხრივ, თუ გვსურს რამდენიმე ბრძანების შესრულება ერთ ტრანზაქციაში, ამის გაკეთება შესაძლებელია შემდეგნაირად:

  • გამორთეთ AutoCommit
  • გამოვიძახეთ ჩვენი ბრძანებები
  • გამოწვიეთ მეთოდი 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  employee SET salary = salary+1000");
 
  connection.commit();

თუ სამუშაოს შესრულებისას მეთოდზე commit() სერვერზე შეცდომა მოხდება, მაშინ SQL-სერვერი გააუქმებს სამივე მოქმედებას.

მაგრამ არსებობს სიტუაციები, როდესაც შეცდომა პიროვნულ კლაინზე ხდება, და ჩვენ ვერ მივაღწიეთ 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  რამდენიმე შეცდომა გამოიწვევს გამონაკლისს");
 
  connection.commit();

თუ ერთ-ერთ executeUpdate() პროცესზე შეცდომა მოხდება, commit() მეთოდი არ გამოძახება. ყველა გაკეთებული ქმედების გაუქმებისთვის, საჭიროა rollback() მეთოდის გამოძახება. ეს ჩვეულებრივ ასე გამოიყურება:


  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  რამდენიმე შეცდომა გამოიწვევს გამონაკლისს");
 
	  connection.commit();
 }
 catch (Exception e) {
   connection.rollback();
}

შენახვის წერტილები

JDBC 3.0-ის გამოჩენით შესაძლებელი გახდა კიდევ უფრო ეფექტურად მუშაობა ტრანზაქციის გაუქმებაზე. ახლა შეგიძლიათ შექმნათ შენახვის წერტილები — save points, და rollback() ოპერაციის გამოძახებისას დაბრუნდეთ კონკრეტულ შენახვის წერტილზე.

შენახვის წერტილის შექმნისთვის უნდა შეიქმნას შენახვის წერტილი, ეს კეთდება ბრძანებით:


   Savepoint save = connection.setSavepoint();

შენახვის წერტილზე დაბრუნება კეთდება ბრძანებით:


   connection.rollback(save);

მოდი ვცადოთ ჩვენი პრობლემური ბრძანების წინ შენახვის წერტილის დამატება:


  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  რამდენიმე შეცდომა გამოიწვევს გამონაკლისს");
 	 }
 	 catch (Exception e) {
    	   connection.rollback(save);
 	 }
 
	  connection.commit();
 }
 catch (Exception e) {
   connection.rollback();
}

ჩვენ მოვაწყვეთ მაგალითი, როდესაც სამუშაო პროცესის მხოლოდ ნაწილის გაუქმება გვჭირდება, პრობლემა ხდება `save-point`-ის წინ დაკევებაზე და გამოძახებით rollback(save) მეთოდზე.

ხო, ეს ძალიან ჰგავს save/load-ს თამაშებში.

Комментарии
ЧТОБЫ ПОСМОТРЕТЬ ВСЕ КОММЕНТАРИИ ИЛИ ОСТАВИТЬ КОММЕНТАРИЙ,
ПЕРЕЙДИТЕ В ПОЛНУЮ ВЕРСИЮ