La principale recherche de cet article est le niveau de session de Hibernate Session_flush et d'isolement. L'introduction et les exemples spécifiques sont les suivants.
Regardons d'abord certains concepts:
1. Dirty Reading: Dirty Reading est également appelé la lecture de données non valides. Cela signifie que pendant l'accès à la base de données, la chose T1 modifie une certaine valeur, puis la chose T2 lit la valeur. Après cela, T1 annule la modification de la valeur pour une raison quelconque, ce qui fait que les données lues par T2 sont invalides. La lecture sale signifie que lorsqu'une chose accéde aux données et modifie les données, et que cette modification n'a pas été soumise à la base de données, une autre chose accède également à ces données, puis utilise ces données. Parce que ces données ne sont toujours pas soumises, les données lues par une autre chose sont des données sales et les opérations effectuées sur la base des données sales sont incorrectes.
2. Pas de lecture répétée: par exemple, lorsque je lisais un post, les données que j'ai trouvées étaient Zhang San et Li SI. Puis, après avoir rafraîchi, j'ai trouvé que le Zhang San initial est devenu Zhang BA. Il s'agit de la lecture dite non répattable, car les données que je lisaient n'ont pas été répétées.
3. Lecture fantastique: Quand je cherchais les données, j'ai commencé à trouver 3 enregistrements. Quand je l'ai rafraîchi, j'ai découvert que les enregistrements devenaient 8. C'est une lecture fantastique.
4. Soumettre la lecture: vous ne pouvez lire qu'après soumettre. Oracle est par défaut. Il n'y a pas de lecture sale de cette manière.
5. Répétabilité: c'est évidemment l'opposé de la lecture non répatiable. Cela peut éviter la lecture non répétée, mais cela ne peut pas éviter la lecture fantôme.
6. Sérialisation: Cette méthode est très stricte. En termes simples, quand je fais quelque chose, personne d'autre ne peut le faire. C'est très sûr, mais c'est extrêmement inefficace.
Ci-dessous, nous utilisons des exemples pratiques pour comprendre l'application de l'autorisation de cache hibernate.
La base de données de cartographie Hibernate est liée à la stratégie de génération de clés principale.
Exemples de génération de clés primaires dans UUID:
classe publique User {private String uid; private String uname; date private date anniversaire; public String getUid () {return uid;} public void setuid (String uid) {this.uid = uid;} public String getUname () {return uname;} public void setuname (string uname) {return anniversaire; SetBirthday (date d'anniversaire) {this.birthday = anniversaire;}}User.hbm.xml:
<? xml version = "1.0"?> <! doctype hibernate mapping public "- // Hibernate / Hibernate mapping dtd 3.0 // en" "http://hibernate.sourcefor.net/hibernate-mapping-3.0.dtd"> <! package = "com.lixue.bean"> <! - Le nom du nœud de classe représente le nom de classe de l'entité, et le tableau représente le nom de l'entité mappée sur la table dans la base de données -> <class name = "user" table = "t_user"> <id name = "uid"> <! - Générer via uUid -> <générateur /> </d> name = "anniversaire" /> </ class> </ hibernate-mapping>
Méthode de test:
/ ** * Testez la stratégie de génération de clé primaire UUID * / public void testsave1 () {/ * Session définie et choses * / session session = null; Transaction transaction = null; essayez {/ * obtenir la session et les choses * / session = hibernateutils.getSession (); transaction = session.begintransaction (); / * Créer l'utilisateur * / utilisateur utilisateur = new user (); user.setUname ("Xi Jinping"); user.setBirthday (new Date ()); / ** * Parce que la stratégie de génération de clés principale de l'utilisateur est UUID, après avoir appelé SAVE, il inclut simplement l'utilisateur dans la gestion de session * L'instruction INSERT ne sera pas émise, mais l'ID a été généré et l'existence enIndateBase dans PersistenceContext est faux * / session.save (utilisateur); / ** * Appeler Flush, Hibernate nettoiera le cache (insérez les objets dans la collection temporaire dans la session-> Insertions dans la base de données, effaçant la collection temporaire) * À l'heure actuelle, les données ne peuvent pas être vues dans la base de données, mais si le niveau d'isolement de la base de données est défini pour ne pas soumettre l'état de la persistance *, alors nous pouvons voir les données d'échoue et les existennes enInl session.flush (); / ** * Soumettre les choses * Par défaut, l'opération de validation effectuera le cache de nettoyage Flush, * afin que les données ne puissent pas être annulées après avoir appelé Flush sans affichage * commit * transaction.Commit (); } catch (exception e) {e.printStackTrace (); transaction.rollback (); } enfin {hibernateUtils.closeSession (session); }} Nous pouvons déboguer le programme à travers des points d'arrêt:
1. Étant donné que le taux secondaire de la génération de clé principale de l'utilisateur est UUID, après avoir appelé la méthode Save (), l'objet utilisateur ne peut être inclus que dans la gestion de la session, et l'instruction d'insertion ne sera pas publiée, mais l'ID a été généré (Remarque: Deux endroits sont très importants après enregistrer. PersistenceContext-> EntityEntries-> map-> table-> Un certain élément de tableau -> La valeur stocke l'objet. Comme indiqué dans l'image:
2. Après avoir appelé la méthode Flush (), la valeur stockée temporaire de l'actionQueue dans la session sera effacée, puis la valeur d'exissindatabase dans la persistanceContext est définie sur true, indiquant qu'il existe des données correspondantes dans la base de données à l'heure actuelle, mais lors de l'ouverture de la base de données et de l'ouverture du tableau, vous ne pouvez pas voir les données, car le niveau d'isolation par défaut de notre MySQL Database est en train de lire. Après avoir appelé la méthode commit (), il existe des données dans la base de données.
Exemple de génération de clés primaires de manière native:
classe publique User11 {private entier uid; private String uname; date privé anniversaire; public Integer getUid () {return uid;} public void setuid (Integer uid) {this.uid = uid;} public String getUname () {return uname;} public void SetUname (string uname) {this.uname = uname;} public dance getbirth () {retourne. anniversaire;} public void SetBirthday (date d'anniversaire) {this.birthday = anniversaire;}}User1.hbm.xml:
<? xml version = "1.0"?> <! doctype hibernate mapping public "- // Hibernate / Hibernate mapping dtd 3.0 // en" "http://hibernate.sourcefor.net/hibernate-mapping-3.0.dtd"> <! package = "com.lixue.bean"> <! - Le nom du nœud de classe représente le nom de classe de l'entité (n'oubliez pas de modifier le nom de classe lors de l'attribution du fichier de mappage, sinon un bogue se produira), le tableau représente le nom de l'entité mappée à la table dans la base de données -> <class name = "user1" Table = "T_User1"> <id name = "uid"> <! </ id> <propriété name = "uname" /> <propriété name = "anniversaire" /> </ class> </ hibernate-mapping>
Méthode de test:
/ ** * Test Stratégie de génération de clé primaire native * / public void testsave2 () {/ * Session définie et choses * / session session = null; Transaction transaction = null; essayez {/ * obtenir la session et les choses * / session = hibernateutils.getSession (); transaction = session.begintransaction (); / * Créer l'utilisateur * / user1 user = new User1 (); user.setUname ("li keqiang"); user.setBirthday (new Date ()); / ** * Parce que la stratégie de génération de clés principale de l'utilisateur1 est native, après l'appel Session.save (), l'instruction INSERT sera exécutée et l'objet de collecte temporaire sera effacé * Renvoyez l'ID généré par la base de données, inclus dans la gestion de la session, et modifié l'existenceIndatabase Status dans la session vers True, * Si le niveau d'isolement de la base de données est défini pour ne pas être lu pour être lu, puis nous pouvons voir les données enregistrées * / Session. transaction.Commit (); } catch (exception e) {e.printStackTrace (); transaction.rollback (); } enfin {hibernateUtils.closeSession (session); }} Déboguer le programme via le point d'arrêt:
1. Étant donné que la stratégie de génération de clés principale est native, après avoir appelé la méthode Save (), l'instruction INSERT sera exécutée et les données de l'objet de collecte temporaire seront effacées et l'ID généré par la base de données sera renvoyé.
2. Incluez l'objet dans la gestion de session, modifiez la propriété existantIndatabase dans PersistenceContext vers True (indique qu'il existe des données correspondantes dans la base de données, mais elle ne peut pas être vue en raison de la zone d'isolement).
Testons une autre méthode d'hibernate, qui est Evict (), ce qui signifie expulser l'objet de la session.
Pour le programme qui génère une stratégie de clé primaire UUID, voici une méthode de test:
/ ** * Testez la stratégie de génération de clé primaire UUID * / public void testsave3 () {/ * Session définie et choses * / session session = null; Transaction transaction = null; essayez {/ * obtenir la session et les choses * / session = hibernateutils.getSession (); transaction = session.begintransaction (); / * Créer l'utilisateur * / utilisateur utilisateur = new user (); user.setUname ("Hu jintao"); user.setBirthday (new Date ()); / ** * Parce que la stratégie de génération de clés principale de l'utilisateur est UUID, après avoir appelé SAVE, l'incorporation de l'utilisateur dans la gestion de session * ne publiera pas l'instruction INSERT, mais l'ID a été généré. Le statut existantIndateBase dans la session est faux * / session.save (utilisateur); / * Expulsion de l'objet utilisateur de la session, c'est-à-dire expulsé de la propriété EntityEntries de la persistancecontext * / session.evict (utilisateur); / ** * ne peut pas soumettre avec succès, car lorsque Hibernate nettoie le cache, l'objet utilisateur est retiré de la session d'inserts la collection temporaire pour insérer * Après l'opération, l'existenceIndatabase dans la propriété EntityEntries doit être mise à jour vers True, et nous appelons la méthode maléfique * Expulsion de l'utilisateur de la session de la session, donc les existencesIndatabase ne peuvent pas être trouvé transaction.Commit (); } catch (exception e) {e.printStackTrace (); transaction.rollback (); } enfin {hibernateUtils.closeSession (session); }} Débogage via des points d'arrêt:
1. Étant donné que la stratégie de génération de clés principale de l'UUID est utilisée, l'instruction INSERT ne sera pas envoyée après avoir appelé la méthode Save (). L'objet est inclus dans la gestion de la session. L'ID a été généré et il n'y a pas de données correspondantes dans la base de données (c'est-à-dire que la valeur d'attribut existantIndatabase est fausse).
2. Après avoir appelé evict (), expulsez l'objet utilisateur de la session, c'est-à-dire expulsé de la propriété EntityEntries du PersistenceContext.
3. Lorsque j'appelle à nouveau la méthode commit (), nous constaterons que nos données ne peuvent pas être enregistrées car au début, notre propriété existenceIndatabase était fausse, c'est-à-dire qu'il n'y a pas de données correspondantes dans la base de données. Ensuite, nous avons appelé Evil () pour supprimer toutes les propriétés des objets dans PersistenceContext (la propriété d'existenceIndatabase est également incluse), mais les données stockées temporaires dans ActionQueue n'ont pas été supprimées. Lorsque nous appelons la méthode commit (), nous appellerons d'abord implicitement la méthode flush (). La fonction de cette méthode a également été mentionnée précédemment. Il insérera l'objet temporaire dans l'actionQueue, puis définira la valeur de propriété existantInTatabase dans le PersistenceContext sur true. Malheureusement, il n'y a pas de propriété existantInatabase dans le PersistenceContext, donc une erreur se produira, entraînant l'incapacité d'économiser.
Pour ce faire, nous améliorons la procédure ci-dessus:
/ ** * Testez la stratégie de génération de clé primaire UUID * / public void testsave4 () {/ * Session définie et choses * / session session = null; Transaction transaction = null; essayez {/ * obtenir la session et les choses * / session = hibernateutils.getSession (); transaction = session.begintransaction (); / * Créer l'utilisateur * / utilisateur utilisateur = new user (); user.setUname ("Hu jintao"); user.setBirthday (new Date ()); / ** * Parce que la stratégie de génération de clés principale de l'utilisateur est UUID, après avoir appelé SAVE, l'incorporation de l'utilisateur dans la gestion de session * ne publiera pas l'instruction INSERT, mais l'ID a été généré. Le statut d'existenceInDateBase dans PersistenceContext est faux * / session.save (utilisateur); / ** * Après Flush, Hibernate nettoiera le cache, enregistrera l'objet utilisateur dans la base de données, effacera l'objet utilisateur dans les insertions de la session * et définisse le statut d'ExistAndatabase dans PersistenceContext sur true * / session.flush (); / * Expulser l'objet utilisateur de la session, c'est-à-dire expulsé de la propriété EntityEntries de persistenceContext * / session.evict (utilisateur); / ** * peut être soumis avec succès car HiberNate ne peut pas être dans la collection d'insertions de session lors du nettoyage du cache * L'objet utilisateur a été trouvé (effacé lorsque Flush a été appelé), de sorte que l'instruction d'insertion ne sera pas émise, ni le statut d'ExistAndatabase dans la session ne sera pas mis à jour * / transaction.cammit (); } catch (exception e) {e.printStackTrace (); transaction.rollback (); } enfin {hibernateUtils.closeSession (session); }} Remarque: Après enregistrer, nous appelons la méthode Flush (), puis appelons la méthode Evict () après le programme modifié.
Débogage via des points d'arrêt:
1. Parce qu'il s'agit toujours d'une stratégie de génération UUID, après avoir appelé SAVE, l'insertion d'insertion ne sera pas publiée, mais l'objet est inclus dans la gestion de la session. La propriété existantIndatabase dans PersistenceContext est fausse.
2. Après avoir appelé Save (), nous appelons à nouveau la méthode flush (). La fonction de cette méthode consiste à nettoyer le cache, c'est-à-dire à publier une instruction INSERT, à insérer l'objet temporaire dans les insertions de la session dans la base de données, puis à effacer la collection temporaire et à définir la propriété existantIndatabase dans la persistenceContext sur true.
3. Après avoir appelé flush (), la méthode Evict () est appelée. Sa fonction consiste à effacer l'objet utilisateur de la session, c'est-à-dire pour effacer la propriété EntityEntries du PersistenceContext.
4. Après avoir appelé la méthode Evict (), la méthode commit () appellera d'abord implicitement la méthode flush (). La fonction de Flush est d'effacer le cache, c'est-à-dire insérer l'objet dans la collection temporaire des insertions dans la base de données, mais nous avons appelé la méthode Flush () avant (Remarque: Après avoir appelé cette méthode, la collection temporaire ne sera donc pas effacée), donc la collection temporaire n'a aucun objet du tout, donc la déclaration d'insertion ne sera pas émise. Il ne mettra pas à jour le statut existantInatabase dans PersistenceContext. Soumettre avec succès.
Voyons utiliser la méthode Evict () dans la stratégie de génération de clés principale native:
/ ** * Test Stratégie de génération de clé primaire native * / public void testsave5 () {/ * Session définie et choses * / session session = null; Transaction transaction = null; essayez {/ * obtenir la session et les choses * / session = hibernateutils.getSession (); transaction = session.begintransaction (); / * Créer l'utilisateur * / user1 user = new User1 (); user.setUname ("Ma ying-jeou"); user.setBirthday (new Date ()); / ** * Étant donné que la stratégie de génération de clés principale de l'utilisateur1 est native, après avoir appelé session.save (), l'instruction d'insertion sera exécutée, * Renvoie l'ID généré par la base de données, inclus dans la gestion de la session, modifiez l'existence de l'état de la base de données de la session, et nous pouvons voir le jeu temporaire * Si le niveau d'isolement de la base de données. / * Expulser l'objet utilisateur de la session, c'est-à-dire expulsé de la propriété EntityEntries de la persistanceContext * / session.evict (utilisateur); / ** * peut être soumis avec succès parce que HiberNate est dans la collecte des insertions de session lors du nettoyage du cache * L'objet utilisateur ne peut être trouvé, donc l'instruction INSERT ne sera pas émise, ni l'état d'existéIndatabase dans la session ne sera pas mis à jour * / transaction.comMit (); } catch (exception e) {e.printStackTrace (); transaction.rollback (); } enfin {hibernateUtils.closeSession (session); }} Par le débogage:
1. Étant donné que la stratégie de génération de clés principale est native, après avoir appelé la méthode de sauvegarde, une instruction INSERT sera publiée immédiatement, renvoyant l'ID généré par la base de données, incorporant l'objet dans la gestion de session, modifiant la propriété d'existenceInatabase dans PersistenceContext à True, c'est-à-dire qu'il existe des données correspondantes dans la base de données, et les objets de la collection temporaire seront effacés. Cependant, en raison du niveau d'isolement MySQL, nous ne pouvons pas voir les données avant de les commettre.
2. Après l'appel de la sauvegarde, l'objet est appelé et l'objet est expulsé de la session, c'est-à-dire qu'il est expulsé des EntityEntries dans la persistenceContext.
3. Après avoir appelé la méthode Evict (), la méthode commit () peut être appelée avec succès. L'engagement peut être enregistré avec succès, car avant d'appeler commit (), la méthode Flush () sera appelée implicitement, c'est-à-dire nettoyer le cache et rechercher des objets dans la collection temporaire à insérer dans la base de données. Cependant, vous constaterez qu'il n'y a pas de données dans la collecte temporaire, de sorte que l'instruction INSERT ne sera pas publiée, et la propriété EXISTENCEIDATABASE dans la persistanceContext ne sera pas mise à jour.
À travers les cas ci-dessus, nous pouvons voir que parfois nous devons appeler la méthode Flush () pour nettoyer le cache. De plus, nous avons également trouvé un problème de ce qui précède, c'est-à-dire que lorsque nous enregistrons () les données, nous ne pouvons pas voir les données avant de les soumettre, c'est-à-dire que le niveau d'isolement de la base de données est limité. Parlons maintenant du niveau d'isolement de MySQL:
1. Vérifiez le niveau d'isolement actuel de la base de données MySQL:
sélectionnez @@ tx_isolation;
Remarque: D'après la figure, nous pouvons voir que le niveau d'isolement par défaut de la base de données MySQL est reproductible, ce qui signifie qu'il n'y aura pas de lecture non répétée, c'est-à-dire qu'elle doit être soumise avant de pouvoir être lue.
2. Modifier le niveau d'isolement actuel de MySQL (en supposant qu'il n'est pas soumis à lire, c'est-à-dire qu'il peut être lu sans validation):
set transaction isolation level read uncommited;
Ce qui précède est toute l'explication détaillée du code de niveau Session_flush et d'isolement d'Hibernate. J'espère que ce sera utile à tout le monde. Les amis intéressés peuvent continuer à se référer à d'autres sujets connexes sur ce site. S'il y a des lacunes, veuillez laisser un message pour le signaler. Merci vos amis pour votre soutien pour ce site!