88 votes

Hibernate : flush() et commit()

Est-ce une bonne pratique d'appeler org.hibernate.Session.flush() séparément ?

Comme indiqué dans org.hibernate.Session docs,

Doit être appelé à la fin d'une unité de travail, avant de valider la transaction et de fermer la session (selon le mode de vidage, Transaction.commit() appelle cette méthode).

Pouvez-vous expliquer le but de l'appel flush() explicitement si org.hibernate.Transaction.commit() le fera déjà ?

105voto

Aleksei Bulgak Points 1502

Dans le manuel d'Hibernate, vous pouvez voir cet exemple

Session session = sessionFactory.openSession();
Transaction tx = session.beginTransaction();

for (int i = 0; i < 100000; i++) {
    Customer customer = new Customer(...);
    session.save(customer);
    if (i % 20 == 0) { // 20, same as the JDBC batch size
        // flush a batch of inserts and release memory:
        session.flush();
        session.clear();
    }
}

tx.commit();
session.close();

Sans l'appel à la méthode flush, votre cache de premier niveau lèverait une exception OutOfMemoryException.

Vous pouvez également consulter cet article sur la chasse d'eau.

93voto

Anand Kulkarni Points 691

flush() synchronisera votre base de données avec l'état actuel de l'objet ou des objets conservés en mémoire, mais ne validera pas la transaction. Donc, si vous obtenez une exception après flush() est appelé, alors la transaction sera annulée. Vous pouvez synchroniser votre base de données avec de petits morceaux de données en utilisant les méthodes suivantes flush() au lieu d'engager un grand nombre de données en une seule fois en utilisant commit() et courir le risque de recevoir un OutOfMemoryException .

commit() rendra permanentes les données stockées dans la base de données. Il n'y a aucun moyen de revenir en arrière sur votre transaction une fois que l'option commit() réussit.

60voto

Nathan Hughes Points 30377

Un cas courant de vidage explicite est celui où vous créez une nouvelle entité persistante et où vous souhaitez qu'une clé primaire artificielle soit générée et lui soit attribuée, afin de pouvoir l'utiliser ultérieurement dans la même transaction. Dans ce cas, l'appel à la purge se traduirait par l'attribution d'un identifiant à votre entité.

Un autre cas de figure est celui où il y a beaucoup de choses dans le cache de premier niveau et où l'on souhaite le vider périodiquement (afin de réduire la quantité de mémoire utilisée par le cache) mais où l'on veut quand même livrer l'ensemble. C'est dans ce cas que Réponse d'Aleksei couvertures.

15voto

Ashu Points 399

flush(); Le vidage est le processus de synchronisation du magasin persistant sous-jacent avec l'état persistant conservé en mémoire. Il mettra à jour ou insérera vos tables dans la transaction en cours, mais il se peut qu'il n'engage pas ces changements.

Vous devez effectuer le rinçage dans le cadre d'un traitement par lots, sinon vous risquez d'obtenir des résultats erronés. OutOfMemoryException.

Commit(); Commit fera commettre la base de données. Lorsque vous avez un objet persistant et que vous modifiez une valeur sur celui-ci, il devient sale et Hibernate a besoin d'envoyer ces changements à votre couche de persistance. Vous devez donc effectuer un commit, mais cela met également fin à l'unité de travail ( transaction.commit() ).

8voto

adn.911 Points 1112

Il n'est généralement pas recommandé d'appeler flush explicitement, sauf si cela est nécessaire. Hibernate appelle généralement automatiquement Flush à la fin de la transaction et nous devons le laisser faire son travail. Dans certains cas, il peut être nécessaire d'appeler explicitement flush lorsqu'une deuxième tâche dépend du résultat de la première tâche de persistance, les deux se trouvant dans la même transaction.

Par exemple, vous pouvez avoir besoin de persister une nouvelle entité et ensuite utiliser l'Id de cette entité pour effectuer une autre tâche dans la même transaction, dans ce cas, il est nécessaire de purger explicitement l'entité d'abord.

@Transactional
void someServiceMethod(Entity entity){
    em.persist(entity); 
    em.flush() //need to explicitly flush in order to use id in next statement
    doSomeThingElse(entity.getId());    
}

Notez également que le vidage explicite ne provoque pas de validation de la base de données, une validation de la base de données n'est effectuée qu'à la fin d'une transaction, donc si une erreur d'exécution se produit après l'appel du vidage, les modifications seront toujours annulées.

Prograide.com

Prograide est une communauté de développeurs qui cherche à élargir la connaissance de la programmation au-delà de l'anglais.
Pour cela nous avons les plus grands doutes résolus en français et vous pouvez aussi poser vos propres questions ou résoudre celles des autres.

Powered by:

X