web-dev-qa-db-fra.com

Utilisation correcte de flush () dans JPA / Hibernate

Je rassemblais des informations sur la méthode flush (), mais je ne sais pas trop quand l'utiliser ni comment l'utiliser correctement. D'après ce que j'ai lu, j'ai cru comprendre que le contenu du contexte de persistance sera synchronisé avec la base de données, i. e. émettre des déclarations en suspens ou actualiser des données d'entité.

Maintenant, j'ai le scénario suivant avec deux entités A et B (dans une relation un à un, mais non appliquée ni modélisée par JPA). A a une PK composite, définie manuellement, ainsi qu'un champ IDENTITY généré automatiquement recordId. Ce recordId doit être écrit dans l'entité B en tant que clé étrangère vers A. J'économise A et B en une seule transaction. Le problème est que la valeur générée automatiquement A.recordId N'est pas disponible dans la transaction, sauf si je passe un appel explicite à em.flush() après avoir appelé em.persist() sur A. (Si j'ai une IDENTITY PK générée automatiquement, la valeur est directement mise à jour dans l'entité, mais ce n'est pas le cas ici.)

_ em.flush() peut-il causer du tort en l'utilisant dans une transaction?

106
MicSim

Les détails exacts de em.flush() dépendent probablement de la mise en œuvre. De manière générale, les fournisseurs JPA tels que Hibernate peuvent généralement mettre en cache les instructions SQL qu’ils sont supposés envoyer à la base de données, souvent jusqu’à ce que vous validiez réellement la transaction. Par exemple, si vous appelez em.persist(), Hibernate se souvient qu'il doit créer une base de données INSERT, mais n'exécute pas réellement l'instruction tant que vous n'avez pas validé la transaction. Afaik, ceci est principalement fait pour des raisons de performance.

Dans certains cas, vous voulez quand même que les instructions SQL soient exécutées immédiatement; généralement lorsque vous avez besoin du résultat d'effets secondaires, comme une clé générée automatiquement ou un déclencheur de base de données.

Ce que em.flush() fait, c'est vider le cache des instructions SQL internes et l'exécuter immédiatement dans la base de données.

En bout de ligne: aucun mal n'est causé, vous pouvez seulement avoir un impact (mineur) sur les performances puisque vous annulez les décisions du fournisseur JPA en ce qui concerne le meilleur moment pour envoyer des instructions SQL à la base de données.

136
Flavio

En fait, em.flush() fait plus que simplement envoyer les commandes SQL mises en cache. Il tente de synchroniser le contexte de persistance avec la base de données sous-jacente. Cela peut entraîner une perte de temps sur vos processus si votre cache contient des collections à synchroniser.

Attention à l'utiliser.

2
Ricardo Nakashima

Em.flush () peut-il causer un préjudice en l'utilisant dans une transaction?

Oui, il peut garder les verrous dans la base de données plus longtemps que nécessaire.

En règle générale, lorsque vous utilisez JPA, vous déléguez la gestion des transactions au conteneur (a.k.a CMT - en utilisant l'annotation @Transactional sur les méthodes métier), ce qui signifie qu'une transaction est automatiquement démarrée lors de la saisie de la méthode et validée/annulée à la fin. Si vous laissez le gestionnaire EntityManager gérer la synchronisation de la base de données, l'exécution des instructions SQL ne sera déclenchée que juste avant la validation, ce qui entraînera des verrous de courte durée dans la base de données. Sinon, vos opérations d'écriture vidées manuellement peuvent conserver des verrous entre le vidage manuel et la validation automatique, ce qui peut être long en fonction du temps d'exécution de la méthode restant.

Remarque qu'une opération déclenche automatiquement un vidage: exécution d'une requête native sur la même session (l'état EM doit être vidé pour être accessible par la requête SQL), insertion d'entités à l'aide d'un identifiant généré de manière native (généré par la base de données, de sorte que l'instruction insert doit être déclenché, l’EM est capable de récupérer l’id généré et de gérer correctement les relations)

1
Gab