Cet article décrit la méthode de fonctionnement du lot Hibernate. Partagez-le pour votre référence, comme suit:
Traitement par lots hibernate
HiberNate exploite complètement la base de données d'une manière orientée objet. Lorsqu'un objet persistant est opéré de manière orientée objet dans le programme, il sera automatiquement converti en opération de la base de données. Par exemple, lors de l'appel de la méthode Delete () de la session pour supprimer un objet persistant, Hibernate sera responsable de la suppression des enregistrements de données correspondants; Lors de l'exécution de la méthode définie de l'objet persistant, Hibernate se convertira automatiquement en méthode de mise à jour correspondante et modifiera les enregistrements correspondants de la base de données.
La question est de savoir si 100 000 enregistrements doivent être mis à jour en même temps, avez-vous besoin de charger 100 000 enregistrements un par un, puis d'appeler la méthode définie à son tour - ce n'est pas seulement lourd, mais aussi les performances de l'accès aux données sont très mauvaises. Pour ce scénario de traitement par lots, Hibernate fournit une solution de traitement par lots. Ce qui suit présente comment faire face à cette situation de traitement par lots à partir de trois aspects: insertion par lots, mise à jour par lots et suppression par lots.
1 insert par lots
Si vous devez insérer 100 000 enregistrements dans la base de données, Hibernate peut généralement utiliser les éléments suivants:
Session session = sessionfactory.opencession (); transaction tx = session.begintransaction (); pour (int i = 0; i <100000; i ++) {utilisateur u = nouvel utilisateur (......); session.save (client);} tx.Commit (); session.close ();Mais au fil de ce programme, il échouera toujours à un moment donné et une exception OutOfMemory est lancée. En effet, la session d'Hibernate contient un cache de niveau 1 requis, et toutes les instances utilisateur seront mises en cache dans la zone de cache au niveau de la session.
Pour résoudre ce problème, il y a une idée très simple: actualiser régulièrement les données mises en cache par la session dans la base de données, plutôt que de les mettre en cache au niveau de la session. Vous pouvez envisager de concevoir un accumulateur, qui augmente de 1 pour chaque instance utilisateur enregistrée. Déterminez si les données du cache de session doivent être rincées dans la base de données en fonction de la valeur de l'accumulateur.
Voici un extrait de code qui ajoute 100 000 instances utilisateur:
Private void TesUser () lève une exception {// Open Session Session Session = HiberNateUtil.currentession (); // Démarrer la transaction de transaction tx = session.begintransaction (); // Loop 100 000 fois et insérer 100 000 enregistrements pour (int i = 0; i <1000000; i ++) {// Créer l'instance utilisateur utilisateur User u1 = new User (); u1.setName ("xxxxx" + i); u1.setage (i); u1.setNationality ("Chine"); // CACH L'INNISE USER SESSESS.SAVE (U1); // chaque fois que l'accumulateur est un multiple de 20, rincez les données de la session dans la base de données et effacez le cache de session if (i% 20 == 0) {session.flush (); session.clear (); tx.Commit (); tx = session.begintransaction (); }} // Commit Transaction tx.Commit (); // Fermer la transaction hibernateutil.closesession ();}Dans le code ci-dessus, lorsque I% 20 == 0, les données mises en cache de la session sont écrites manuellement dans la base de données et la transaction est soumise manuellement. Si la transaction n'est pas soumise, les données seront toujours mises en cache dans le bureau des transactions - il n'a pas saisi la base de données, ce qui entraînera également une exception de débordement de mémoire.
Il s'agit du traitement du cache au niveau de la session, et le cache secondaire de SessionFactory doit également être désactivé par la configuration suivante.
hibernate.cache.use_second_level_cache false
Remarque: En plus de nettoyer manuellement le cache au niveau de la session, il est préférable de désactiver le cache secondaire de niveau SessionFactory. Sinon, même si le cache au niveau de la session est effacé manuellement, une exception peut être lancée car il y a toujours un cache au niveau SessionFactory.
2 mises à jour par lots
La méthode décrite ci-dessus convient également aux données de mise à jour par lots. Si vous avez besoin de renvoyer plusieurs lignes de données, vous pouvez utiliser la méthode Scroll () pour utiliser pleinement les avantages des performances apportés par les curseurs côté serveur. Voici un extrait de code pour les mises à jour par lots:
Private void TesUser () lève une exception {// Open Session Session Session = HiberNateUtil.currentession (); // Démarrer la transaction de transaction tx = session.begintransaction (); // interroge tous les enregistrements dans la table utilisateur ScrollableResults Users = Session.CreateeQuery ("From User") .setCacheMode (CacheMode.Ignore) .Scroll (ScrollMode.Forward_only); int count = 0; // Transaction Tous les enregistrements dans la table utilisateur while (users.next ()) {utilisateur u = (utilisateur) Users.get (0); U.SetName ("Nouveau nom d'utilisateur" + Count); // lorsque le nombre est un multiple de 20, rincez le résultat mis à jour de la session à la base de données if (++ count% 20 == 0) {session.flush (); session.clear (); }} tx.Commit (); HibernateUtil.closeSession ();} De cette façon, bien que les mises à jour par lots puissent être effectuées, l'effet est très médiocre. L'efficacité d'exécution n'est pas élevée et la requête de données est requise en premier, puis la mise à jour des données est effectuée. Cette mise à jour sera une mise à jour en ligne par ligne, c'est-à-dire chaque fois qu'une ligne d'enregistrements est mise à jour, une instruction de mise à jour doit être exécutée et les performances sont très faibles.
Pour éviter cela, Hibernate fournit une syntaxe HQL similaire à SQL pour les mises à jour par lots et la suppression par lots.
3 mises à jour par lots de style SQL / Suppression
Les instructions HQL fournies par HiberNate prennent également en charge la mise à jour par lots et la syntaxe de supprimer.
Le format de syntaxe des instructions de mise à jour par lots et de suppression est la suivante:
Mise à jour | Supprimer? ClassName [Where Where_Conditions]
Il y a quatre points à noter sur le format de syntaxe ci-dessus:
● Dans la clause From, le mot-clé depuis est facultatif. Autrement dit, vous ne pouvez pas du tout écrire à partir de mots clés.
● Il ne peut y avoir qu'un seul nom de classe dans la clause From, et le nom de classe ne peut pas avoir d'alias.
● Vous ne pouvez pas utiliser les connexions dans des instructions HQL par lots, ni explicites ni implicites. Mais les sous-requêtes peuvent être utilisées dans la clause WHERE.
● L'ensemble de la clause où est facultatif.
En supposant que vous devez modifier par lots l'attribut de nom de l'instance de classe utilisateur, vous pouvez utiliser l'extrait de code suivant:
Private void TesUser () lève une exception {// Open Session Session Session = HiberNateUtil.currentession (); // Démarrer la transaction de transaction tx = session.begintransaction (); // Définir la mise à jour du lot HQL String string hqlupdate = "update user set name =: newname"; // Exécuter Mise à jour int mises à jour = session.createeQuery (hQlupDate) .SetString ("newname", "nouveau nom") .ExECuteUpdate (); // commit la transaction tx.commit (); HibernateUtil.closeSession ();}Comme on peut le voir à partir du code ci-dessus, cette syntaxe est très similaire à la syntaxe ExecuteUpdate de préparation. En fait, cette mise à jour par lots de HQL emprunte directement à l'instruction de mise à jour de la syntaxe SQL.
Remarque: Lorsque vous utilisez cette syntaxe de mise à jour par lots, vous n'avez généralement besoin d'exécuter une instruction SQL Update une fois pour terminer toutes les mises à jour qui répondent aux enregistrements conditionnels. Mais il peut également être nécessaire d'exécuter plusieurs instructions de mise à jour, car il existe des cas particuliers tels que la cartographie des successions, comme une instance de personne, qui a une instance de sous-classe de client. Lorsque le lot met à jour les instances de la personne, l'instance client doit également être mise à jour. Si vous utilisez la stratégie de mappage de sous-classe ou de sous-classe Union, les instances de personne et de client sont enregistrées dans différentes tables, de plus en plusieurs relevés de mise à jour peuvent être nécessaires.
Exécutez une suppression HQL et utilisez la méthode query.executeUpdate (). Ce qui suit est un extrait de code qui supprime tous les enregistrements ci-dessus à la fois:
Private void TesUser () lève une exception {// Open Session Instance Session Session = HiberNateUtil.Currentession (); // Démarrer la transaction de transaction tx = session.begintransaction (); // Définir la suppression de suppression de lots HQL String hqlupdate = "Delete User"; // Exécuter la suppression de lots int à jour de mise à jour = session.CreateeQuy (hqlupdate) .ExECuteUpdate (); // commit la transaction tx.commit (); // Fermer ses session hibernateutil.closesession ();}Renvoie une valeur entière par la méthode query.executeUpdate (), qui est le nombre d'enregistrements affectés par cette opération. En fait, les opérations sous-jacentes d'Hibernate se font via JDBC. Par conséquent, s'il existe des lots d'opérations de mise à jour ou de suppression qui sont converties en plusieurs instructions de mise à jour ou de suppression, la méthode renvoie le nombre d'enregistrements affectés par la dernière instruction SQL.
J'espère que la description de cet article sera utile à la programmation Java de chacun basée sur le cadre d'hibernate.