5
votes

À quoi sert @Transactional avec JPA et Hibernate?

J'apprends à créer une API REST avec JPA et Hibernate et une base de données MySQL et je vois cette annotation @Transactional. Quelqu'un peut-il expliquer à quoi sert cette annotation?

Par exemple, j'ai cette classe DAO simple:

@Repository
public class EmployeeDAOHibernateImpl implements EmployeeDAO {

    // define field for entitymanager
    private EntityManager entityManager;

    // set up constructor injection
    @Autowired
    public EmployeeDAOHibernateImpl(EntityManager entityManager) {
        this.entityManager = entityManager;
    }

    @Override
    @Transactional
    public List<Employee> findAll() {

        // get the current hibernate session
        Session currentSession = entityManager.unwrap(Session.class);

        // create a query
        Query<Employee> theQuery = 
                currentSession.createQuery("from Employee", Employee.class);

        // execute query and get result list
        List<Employee> employees = theQuery.getResultList();

        // return the results
        return employees;
    }

}

Vous pouvez voir le @Transactional utilisé pour la méthode findAll (), mais si je supprime ce @Transactional, j'obtiens le même sortie ... alors à quoi sert ce @Transactional?


2 commentaires

Copie possible de ​​Spring - @Transactional - Que se passe-t-il en arrière-plan?


Cela n'a rien à voir avec JPA ... FWIW. C'est le printemps


4 Réponses :


0
votes

Pour vous familiariser avec l'annotation @Transactional en général, veuillez consulter cet article . Pour creuser plus profondément, veuillez vous reporter au printemps docs < / a>.


0 commentaires

16
votes
L'annotation

@Transactional est utilisée lorsque vous voulez qu'une certaine méthode / classe (= toutes les méthodes à l'intérieur) soit exécutée dans une transaction.

Supposons que l'utilisateur A veuille transférer 100 $ à l'utilisateur B . Ce qui se passe est:

  1. Nous diminuons le compte de A de 100 $
  2. Nous ajoutons 100 $ au compte de B

Supposons que l'exception soit lancée après avoir réussi 1) et avant d'exécuter 2) . Maintenant, nous aurions une sorte d'incohérence car A a perdu 100 $ alors que B n'a rien obtenu. Les transactions signifient tout ou rien. S'il y a une exception levée quelque part dans la méthode, les modifications ne sont pas conservées dans la base de données. Une chose appelée rollback se produit.

Si vous ne spécifiez pas @Transactional , chaque appel DB sera dans une transaction différente.


1 commentaires

une bonne réponse mais une chose doit être ajoutée - en cas d'exemple de code @Transactional n'est pas nécessaire, c'est peut-être une "programmation superstitieuse" où quelqu'un ajoute toujours @Transactional même si cela n'a aucun effet "juste au cas où ":)



12
votes

En général, l'annotation @Transactional est écrite au niveau du service.

Il est utilisé pour combiner plusieurs écritures sur une base de données en une seule opération atomique .

Quand quelqu'un appelle la méthode annotée avec @Transactional tout ou aucune des écritures sur la base de données est exécutée .

Dans le cas d'opérations de lecture, ce n'est pas utile et c'est le cas dans le cas d'une seule écriture atomique. Vous l'utilisez en une seule lecture (sélectionnez) donc l'ajout ou la suppression de l'annotation @Transactional n'a aucun impact.


3 commentaires

Dans les opérations de lecture, il est utile si vous utilisez Java Streams pour placer les résultats de sélection ...


il vaut la peine d'ajouter que @Transactional doit être utilisé lorsqu'il y a plusieurs mises à jour d'entité qui est dans l'état persistant (géré par le gestionnaire d'entités), donc save () < / code> ne peut pas être explicitement mis dans le code mais les setters sont appelés sur entity


@viruskimera pouvez-vous élaborer ou fournir un lien?



0
votes

La classe déclare @Transactional sur elle-même ou sur ses membres, Spring crée un proxy qui implémente la ou les mêmes interfaces que la classe que vous annotez. En d'autres termes, Spring enveloppe le bean dans le proxy et le bean lui-même n'en a pas connaissance .

Un proxy permet à Spring d'injecter des comportements avant, après ou autour des appels de méthode dans l'objet faisant l'objet d'un proxy.

En interne, c'est la même chose que d'utiliser un avis de transaction (en utilisant AOP), où un proxy est créé en premier et est appelé avant / après la méthode du bean cible.

L'objet proxy généré est fourni avec un TransactionInterceptor , qui est créé par Spring. Ainsi, lorsque la méthode @Transactional est appelée à partir du code client, le TransactionInterceptor est d'abord appelé à partir de l'objet proxy, qui commence la transaction et appelle finalement la méthode sur le bean cible. Une fois l'appel terminé, le TransactionInterceptor valide / annule la transaction en conséquence


0 commentaires