Активиране на заключванията на транзакции в Spring Data JPA

1. Общ преглед

В този бърз урок ще обсъдим активирането на заключване на транзакции в Spring Data JPA за персонализирани методи за заявка и предварително дефинирани CRUD методи за хранилище.

Също така ще разгледаме различните видове заключване и ще зададем времето за изчакване на заключване на транзакциите.

2. Видове заключване

JPA има дефинирани два основни типа заключване, които са Песимистично заключване и Оптимистично заключване.

2.1 Песимистично заключване

Когато използваме песимистично заключване в транзакция и имаме достъп до обект, той ще бъде заключен незабавно . Транзакцията освобождава заключването или чрез ангажиране, или отменяне на транзакцията.

2.2 Оптимистично заключване

В Оптимистично заключване транзакцията не заключва обекта веднага. Вместо това транзакцията обикновено запазва състоянието на обекта с присвоен номер на версията.

Когато се опитваме да актуализираме състоянието на обекта в различна транзакция, транзакцията сравнява записания номер на версията със съществуващия номер на версия по време на актуализация.

В този момент, ако номерът на версията се различава, това означава, че обектът не може да бъде модифициран. Ако има активна транзакция, тогава тази транзакция ще бъде върната и основната реализация на JPA ще хвърли OptimisticLockException.

Освен подхода на версията, можем да използваме и други подходи като времеви клейма, изчисление на хеш стойност или сериализирана контролна сума, в зависимост от това кой подход е най-подходящ за текущия ни контекст на развитие.

3. Активиране на заключването на транзакции на методи за заявки

За да придобием заключване на обект, можем да анотираме метода на целевата заявка с анотация на заключване, като предадем необходимия тип режим на заключване .

Типовете режим на заключване са стойности на изброяване, които трябва да бъдат посочени при заключване на обект. След това посоченият режим на заключване се разпространява в базата данни, за да приложи съответното заключване върху обекта на обекта.

За да зададем заключване на персонализиран метод на заявка на JPA хранилище Spring Data, можем да анотираме метода с @Lock и да посочим необходимия тип режим на заключване:

@Lock(LockModeType.OPTIMISTIC_FORCE_INCREMENT) @Query("SELECT c FROM Customer c WHERE c.orgId = ?1") public List fetchCustomersByOrgId(Long orgId);

За да наложим заключването на предварително дефинирани методи на хранилище като findAll или findById (id) , трябва да декларираме метода в хранилището и да анотираме метода с анотацията Lock :

@Lock(LockModeType.PESSIMISTIC_READ) public Optional findById(Long customerId);

Когато заключването е изрично разрешено и няма активна транзакция, основното изпълнение на JPA ще хвърли TransactionRequiredException .

В случай че заключването не може да бъде предоставено и конфликтът на заключване не доведе до връщане на транзакция, JPA хвърля LockTimeoutException . Но това не означава активната транзакция за връщане назад.

4. Задаване на изчаквания за заключване на транзакции

Когато използвате песимистично заключване, базата данни ще се опита незабавно да заключи обекта. Основната реализация на JPA изхвърля LockTimeoutException, когато заключването не може да бъде получено веднага. За да избегнем подобни изключения, можем да посочим стойността на времето за изчакване на заключването.

В Spring Data JPA времето за изчакване на заключването може да бъде посочено с помощта на анотацията QueryHints чрез поставяне на QueryHint върху методи за заявка:

@Lock(LockModeType.PESSIMISTIC_READ) @QueryHints({@QueryHint(name = "javax.persistence.lock.timeout", value = "3000")}) public Optional findById(Long customerId);

Допълнителни подробности за задаване на намек за изчакване за заключване при различни обхвати можете да намерите в тази статия на ObjectDB.

5. Заключение

В този урок научихме различните видове режими на заключване на транзакции. Научихме как да активираме заключване на транзакции в Spring Data JPA. Покрихме и настройките за изчакване за заключване.

Прилагането на правилните заключения на транзакции на правилните места може да помогне за поддържане на целостта на данните в приложения за едновременно използване на голям обем.

Когато транзакцията трябва стриктно да се придържа към правилата на ACID, трябва да използваме песимистично заключване. Оптимистично заключване трябва да се прилага, когато трябва да разрешим множество едновременни четения и когато евентуална последователност е приемлива в контекста на приложението.

Разбира се, примерният код за Песимистично заключване и Оптимистично заключване може да бъде намерен в Github.