Hibernate hql, exécute plusieurs instructions de mise à jour dans la même requête
Je veux exécuter plusieurs instructions update dans la même requête dans hibernate Hql.
comme ci-dessous:
hql = " update Table1 set prob1=null where id=:id1; "
+ " delete from Table2 where id =:id2 ";
...
query.executeUpdate();
dans le même executeUpdate
appel je veux mettre à jour des enregistrements dans la table Table1 et supprimer des enregistrements à partir de Table2.
Est-ce possible?
source d'informationauteur Nebras
Vous devez vous connecter pour publier un commentaire.
En bref, ce que vous recherchez est quelque chose comme le dosage en JDBC. Thich n'est pas fournie par Hibernate pour Vrac requête de mise à Jour, et je doute que va jamais être considéré pour la mise en veille prolongée.
À partir de mon expérience passée, la fonction de traitement par lot pour HQL est rarement utile dans la vie réelle. Il peut sembler étrange que quelque chose est utile dans SQL+JDBC, mais pas dans les requêtes HQL. Je vais essayer d'expliquer.
Généralement, lorsque l'on travail avec mise en veille prolongée (ou d'autres ORM), nous travaillons à l'encontre des entités. Hibernate sera responsable de synchroniser nos entités de l'état avec la DB, ce qui est généralement le cas que JDBC dosage peuvent aider à améliorer les performances. Cependant, dans Hibernate on ne change pas à chaque entité de l'état en Vrac requête de mise à Jour.
Juste donner un exemple, en pseudo-code:
Dans JDBC, vous pouvez faire quelque chose comme (je suis en train d'essayer d'imiter ce que vous montrez dans votre exemple):
Naïf de traduction à partir de JDBC logique de mise en veille prolongée peut vous donner quelque chose comme ceci:
Je soupçonne que vous pensez que vous avez besoin de la fonction de traitement par lot parce que vous faites quelque chose de similaire (selon votre exemple, vous utilisez la mise à jour en bloc pour chaque enregistrement). Toutefois, il est PAS comment la chose devrait être fait dans Hibernate/JPA,
(En fait, il est préférable d'envelopper la couche de persistance de l'accès par le biais d'un référentiel, ici, je suis juste à la simplification de l'image)
Ce faisant, Hibernate est assez intelligent pour détecter modifiés/supprimés/inséré entités, et de rendre l'utilisation de JDBC lot pour faire de la DB de la CUD opérations à
flush()
. Le plus important, c'est le but entier de l'ORM: nous voulons offrir le comportement riche entités de travailler avec, pour les internes de modification de l'état des entités peut être de façon "transparente" réfléchie dans le stockage persistant.HQL mise à Jour en bloc vise pour un autre usage, qui est quelque chose comme une mise à jour en bloc DB à affecter un grand nombre d'enregistrements, par exemple:
Il est rarement nécessaire pour l'exécution d'un lot de requêtes dans ce genre de scénario d'utilisation, par conséquent, les frais généraux de la DB aller-retour est insignifiant, et, par conséquent, de prestations et de traitement par lots de soutien pour le vrac requête de mise à jour est rarement significative.
Je ne peux pas omettre qu'il y a des cas que vous avez vraiment besoin d'émettre beaucoup de requêtes de mise à jour qui n'est pas approprié de faire une véritable entité comportement. Dans de tels cas, vous pouvez vouloir reconsidérer si Hibernate est le bon outil pour être utilisé. Vous pouvez envisager d'utiliser pur JDBC dans de tels cas d'utilisation de sorte que vous avez le contrôle sur la façon dont les requêtes sont émises.
Non, il n'est pas possible, parce que Hibernate utilise
PreparedStatement
s (ce qui est une bonne raison de lier les variables), etPreparedStatement
s ne prennent pas en charge les lots constitués de plusieurs différents états.PreparedStatement
ne peut en lots de différentes combinaisons de variables de liaison pour une déclaration, qui Hibernate utilise pour lot insertions/mises à jour lors de la chasse des changements dans le contexte de persistance (session).executeUpdate()
exécute une seule requête de mise à jour.Donc, non, vous ne pouvez pas le faire. Vous avez à réaliser que de nombreuses requêtes de mise à jour sous forme de tables à mettre à jour/supprimer.
En outre, il fait un code plus propre si vous avez des requêtes distinctes :
executeUpdate()
Cela ne veut pas dire que les requêtes doivent obligatoirement être transmisent un par un.
Le Traitement par lots est une fonctionnalité fournie par Hibernate pour améliorer les performances lorsque vous voulez exécuter de multiples requêtes. Vous devez l'activer pour pouvoir l'utiliser.
hibernate.jdbc.batch_size
propriété doit être définie avec une valeur appropriée.En plus de la documentation officielle :
Néanmoins, dans votre cas, il sera inutile parce que Dragan Bozanovic expliqué mise à jour/supprimer des tables dans vos requêtes. Donc, il serait de créer autant de lots exécutions interrogé tables.
Donc, vous devez exécuter chaque requête individuelle. Juste commit() de la transaction lorsque vous le jugez il devrait être :
Le SQL généré par JPA en vrac mises à jour ou suppressions, c'est à dire des appels à javax.la persistance.De la requête.executeUpdate() ne peut pas être groupées par Hibernate lorsqu'elle est transmise via JDBC. @DraganBozanovic et @AdrianShum l'ai déjà expliqué cela, mais pour ajouter à leurs commentaires: executeUpdate() retourne un int (le nombre d'entités mises à jour ou effacées) - indépendamment de rinçage de la session Hibernate, comment l'int être retournée sans l'appel de la base de données immédiatement et de façon synchrone? Le JPQL/HQL/SQL devra être évaluée côté client, ce qui n'est pas possible parce que les entités en vrac mis à jour/modifiés /supprimés n'ont même pas été lus dans la session Hibernate. En outre, si la mise à jour/supprimer n'ont pas été exécutés sur la base de données immédiatement, les requêtes suivantes à lire dans des entités JPA pourrait obtenir des données périmées. Exemple:
Si le executeUpdate à 1 ont pu être reporté jusqu'à ce que la lecture à 2, alors vous obtenez la mauvaise réponse (Client existe toujours).
Vous avez besoin de lire les entités en utilisant JPA, mettre à jour, et laisser Hibernate générer la mise à jour de SQL (ce qui peut lots), ou d'appels JDBC directement pour effectuer des mises à jour par lot.
Pourquoi ne pas exécuter deux requêtes séparément dans une méthode
En annotant la méthode avec @Transactional, si la requête échoue, l'autre ne sera pas exécuté.