Erreur TransactionRequiredException

1. Vue d'ensemble

Dans ce didacticiel, nous allons examiner la cause de l' erreur TransactionRequiredException et comment la résoudre.

2. TransactionRequiredException

Cette erreur se produit généralement lorsque nous essayons d'effectuer une opération de base de données qui modifie la base de données sans transaction .

Par exemple, essayer de mettre à jour un enregistrement sans transaction:

Query updateQuery = session.createQuery("UPDATE Post p SET p.title = ?1, p.body = ?2 WHERE p.id = ?3"); updateQuery.setParameter(1, title); updateQuery.setParameter(2, body); updateQuery.setParameter(3, id); updateQuery.executeUpdate();

Lèvera une exception avec un message du type suivant:

... javax.persistence.TransactionRequiredException: Executing an update/delete query at org.hibernate.query.internal.AbstractProducedQuery.executeUpdate(AbstractProducedQuery.java:1586) ...

3. Fourniture d'une transaction

La solution évidente consiste à encapsuler toute opération de modification de base de données dans une transaction:

Transaction txn = session.beginTransaction(); Query updateQuery = session.createQuery("UPDATE Post p SET p.title = ?1, p.body = ?2 WHERE p.id = ?3"); updateQuery.setParameter(1, title); updateQuery.setParameter(2, body); updateQuery.setParameter(3, id); updateQuery.executeUpdate(); txn.commit();

Dans l'extrait de code ci-dessus, nous lançons et validons manuellement la transaction. Bien que dans un environnement Spring Boot, nous pouvons y parvenir en utilisant l' annotation @Transactional .

4. Prise en charge des transactions au printemps

Si nous voulons un contrôle plus fin, nous pouvons utiliser le TransactionTemplate de Spring . Parce que cela permet au programmeur de déclencher la persistance d'un objet immédiatement avant de procéder à l'exécution du code d'une méthode.

Par exemple, disons que nous voulons mettre à jour le message avant d'envoyer une notification par e-mail:

public void update() { entityManager.createQuery("UPDATE Post p SET p.title = ?2, p.body = ?3 WHERE p.id = ?1") // parameters .executeUpdate(); sendEmail(); }

L'application de @Transactional à la méthode ci-dessus peut entraîner l'envoi de l'e-mail malgré une exception dans le processus de mise à jour. En effet, la transaction ne sera validée que lorsque la méthode se termine et est sur le point de revenir à l'appelant.

Par conséquent, la mise à jour de la publication dans un TransactionTemplate empêchera ce scénario car elle validera l'opération immédiatement:

public void update() { transactionTemplate.execute(transactionStatus -> { entityManager.createQuery("UPDATE Post p SET p.title = ?2, p.body = ?3 WHERE p.id = ?1") // parameters .executeUpdate(); transactionStatus.flush(); return null; }); sendEmail(); }

5. Conclusion

En conclusion, il est généralement recommandé d'encapsuler les opérations de base de données dans une transaction. Cela aide à prévenir la corruption des données. Le code source complet est disponible à l'adresse over sur Github.