Vous serez forcement en auto-commit sur une base HSQLDB ou avec des tables MyISAM sur mySQL. Sinon il faut vous assurer que votre base/driver jdbc n’est pas configuré en auto-commit
Les déploiements en EJB = la transaction est gérée par le serveur d’appli / EJB transaction support
Les déploiements en webapp seule avec tomcat (nos images sim/docker) = accès direct via driver SQL. Les objectDB sont pilotés par le paramètre DIRECT_TRANSACTION
Il vaut “no” par défaut = toutes les mises à jour sont en auto-commit, dans ce cas il faut gérer le rollback applicatif par des “update” inverses dans un catch
Le passer à “yes” = tout objet qui fait un create/update/save/delete arme une transaction, et tous les hooks enfants (postSave…) utiliseront cette transaction (dans un même thread, si on utilise un autre thread genre on appelle une action asynchrone ça sortira de la transaction).
Ce n’est pas le mode par défaut car si certaines transactions sont longues, le commited read en lecture bloquera pas mal d’utilisateurs si c’est une action synchrone/UI.
Pour faire une simple transaction par code en laissant le paramètre global à “no” et en restant dans le thread de session :
Grant g = getGrant();
try {
g.beginTransaction();
// ....
obj1.save();
obj2.save();
// postSave... hooks can include other updates in the same transaction
obj3.delete();
// ....
if (error)
g.rollbackTransaction();
else
g.commitTransaction();
}
catch (Exception e) {
g.rollbackTransaction();
}
Attention
ces verbes ne feront rien si la base est en auto-commit
si votre transaction est longue et bloque les accès en lecture, il y aura aussi à vérifier les timeout configurés côté base (long transaction, taille max des locks, mode de verrouillage page/row…).
Perso, je préfère toujours laisser le système fluide / auto-commit / sans passer par les DBA… en gérant les erreurs par des “update” qui annulent applicativement les choses ou par job/cron de nettoyage asynchrone.