web-dev-qa-db-fra.com

Hibernate commit () et flush ()

Je googlé beaucoup et lu sur org.hibernate.Transaction.commit() et org.hibernate.Session.flush() beaucoup, connaître le but de chaque méthode, mais toujours une question.

Est-ce une bonne pratique d'appeler la méthode org.hibernate.Session.flush() à la main? Comme indiqué dans la documentation org.hibernate.Session,

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

Pourriez-vous m'expliquer le but d'appeler org.hibernate.Session.flush() à la main si org.hibernate.Transaction.commit() l'appellera automatiquement?

Merci!

64
bsiamionau

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 de la méthode flush, votre cache de premier niveau lève une exception OutOfMemoryException.

Vous pouvez aussi regarder ce post sur le flushing

84
Aleksei Bulgak

flush() synchronisera votre base de données avec l'état actuel du ou des objets stockés dans la mémoire, mais ne commettra pas la transaction. Ainsi, si vous obtenez une exception après l'appel de flush(), la transaction sera annulée. Vous pouvez synchroniser votre base de données avec de petites quantités de données en utilisant flush() au lieu de valider une grande quantité de données à la fois en utilisant commit() et vous exposez au risque d'obtenir un Exception de mémoire insuffisante .

commit() rendra permanentes les données stockées dans la base de données. Vous ne pouvez pas annuler votre transaction une fois que la fonction commit() a réussi.

58
Anand Kulkarni

Un cas courant pour le vidage explicite est lorsque vous créez une nouvelle entité persistante et que vous souhaitez qu’une clé primaire artificielle soit générée et affectée, de sorte que vous puissiez l’utiliser ultérieurement dans la même transaction. Dans ce cas, appeler un flush donnerait à votre entité un identifiant.

Un autre cas est le cas où il y a beaucoup d'éléments dans le cache de niveau 1 et que vous souhaitez le vider périodiquement (afin de réduire la quantité de mémoire utilisée par le cache), mais que vous souhaitez tout de même tout mettre ensemble. . C'est le cas que la réponse d'Aleksei couvre (+1 de moi).

47
Nathan Hughes

flush (); Flushing est le processus de synchronisation du magasin persistant sous-jacent avec un état persistant conservé dans memory.it sera mis à jour ou inséré dans vos tables dans la transaction en cours d'exécution, mais il ne peut pas valider ces modifications.

Vous devez vider le traitement par lots sinon cela peut donner OutOfMemoryException.

Commit (); Engit validera la base de données. Lorsque vous avez un objet persistant et que vous modifiez une valeur dessus, il devient sale et la veille prolongée doit effacer ces modifications dans votre couche de persistance. commit mais cela met également fin à l'unité de travail .transaction.commit ()

12
Ashu

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

Par exemple, vous devrez peut-être conserver une nouvelle entité, puis 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 vider explicitement l'entité en premier.

@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 est effectuée uniquement à la fin d'une transaction. Par conséquent, si une erreur d'exécution se produisait après l'appel du vidage, les modifications étaient toujours restaurées.

5
adn.911

Par défaut, le mode de vidage est AUTO, ce qui signifie: "La session est parfois vidée avant l'exécution de la requête afin de garantir que les requêtes ne retournent jamais à l'état obsolète", mais la session est généralement vidée lorsque vous validez vos modifications. L'appel manuel de la méthode flush est utile lorsque vous utilisez FlushMode = MANUAL ou si vous souhaitez effectuer une sorte d'optimisation. Mais comme je n’ai jamais fait cela, je ne peux pas vous donner de conseils pratiques.

3
dimas

session.flush () est une méthode de synchronisation pour insérer des données dans la base de données séquentiellement. Si nous utilisons cette méthode, les données ne seront pas stockées dans la base de données, mais stockées en cache. Si une exception devait se produire au milieu, nous pouvons la gérer. Mais commit (), il stockera les données dans la base de données. Si nous stockons plus de données, il peut y avoir une chance de sortir de l’exception de mémoire, comme dans le programme JDBC dans le sujet Point de sauvegarde.

2
Gautam Prusty