cache
Aujourd'hui, nous parlerons de l'État entité et du cache hibernate en hibernate.
1) Tout d'abord, jetons un coup d'œil au statut de l'entité:
Il existe trois principaux types d'états d'entités: transitoires, persistants et détachés.
Vous le comprenez probablement en lisant l'anglais.
Transient: fait référence aux données qui ne correspond pas encore aux données de la base de données.
Persistant: fait référence aux données correspondant aux données de la base de données, et toute modification de celle-ci sera reflétée dans la base de données.
Détaché: fait référence aux données correspondant aux données de la base de données, mais comme la session est fermée, les modifications qu'il apporte n'affectera pas les enregistrements de la base de données.
Codez directement:
Transaction tx = session.begintransaction (); Utilisateur utilisateur = nouveau utilisateur (); user.setName ("shun"); // L'utilisateur ici n'a pas été enregistré dans la base de données, et il n'y a pas d'enregistrement correspondant dans la table de base de données. Il s'agit d'une session d'état transitoire.save (utilisateur); tx.Commit (); // Après engagement, l'utilisateur devient une session d'état persistante.close (); // Parce que la session est fermée, l'utilisateur est détaché pour le moment et toutes ses modifications ne seront pas reflétées dans la base de données. Session Session2 = SessionFactory.OpenSession (); tx = session2.begintransaction (); user.setName ("shun123"); Session2.SaveorUpDate (utilisateur); tx.Commit (); // Lorsque nous appelons SaveorUpdate, l'utilisateur redevient persistant et toutes ses modifications seront reflétées dans la base de données. session2.close (); Nous voyons le code. Tout d'abord, nous définissons un utilisateur d'objet. Avant d'être enregistré, c'est l'état transitoire et il n'y a pas d'enregistrement correspondant dans la base de données. Lorsque nous enregistrons et soumettons la modification, l'utilisateur devient un état persistant et il y a un enregistrement correspondant dans la base de données. Lorsque nous fermons la session, l'utilisateur se détache et ses modifications ne seront pas reflétées dans la base de données à moins que nous appelons manuellement les méthodes de mise à jour et d'addition correspondantes telles que SaveorUpdate. Et que devons-nous faire lorsque nous voulons que cela passe d'un état persistant à transitoire? Supprimez-le simplement directement. Après la suppression, l'objet n'aura aucun enregistrement correspondant dans la base de données, qui deviendra transitoire.
La transition d'état de l'hibernate est relativement simple. Lorsqu'il est transitoire, il n'y a pas d'enregistrement correspondant pour la base de données, tandis que persistant et détaché ont des enregistrements correspondants. Cependant, la seule différence est que détaché est un État qui n'existe que après la fermeture de la session. Alors, quelle est la différence entre transitoire et détaché? Il s'agit simplement de savoir s'il existe un enregistrement de table de base de données correspondant.
2) Après avoir lu le statut, jetons un coup d'œil à la cache d'hibernate
Il existe deux types de caches pour Hibernate: Cache de niveau 1 et cache de niveau 2.
Cache de niveau 1: le cache soi-disant de niveau 1 est le cache interne.
Cache de niveau 2: il comprend le cache au niveau de l'application, qui est appelé cache SessionFactory dans Hibernate, et l'autre est le cache distribué, qui est la méthode de cache la plus sûre.
Jetons un œil au programme directement:
public static void main (String [] args) {configuration cfg = new configuration (). configure (); SessionFactory SessionFactory = cfg.BuildSessionFactory (); Session Session = SessionFactory.OpenSession (); User user = (utilisateur) session.load (user.class, new long (29)); System.out.println (user.getName ()); User user2 = (utilisateur) session.load (user.class, new long (29)); System.out.println (user2.getName ()); session.close (); } Voir les résultats:
Hibernate: sélectionnez user0_.user_id en tant qu'utilisateur1_0_0_, user0_.user_name en tant qu'utilisateur2_0_0_, user0_.age en tant qu'âge 00_0_ de l'utilisateur user0_ où user0_.user_id =? shun123123 shun123123
Dans l'exemple, nous avons utilisé le chargement deux fois, mais il n'y avait qu'une seule instruction SQL dans le résultat, ce qui a indiqué qu'il n'avait été interrogé qu'une seule fois.
Pourquoi? C'est pourquoi le cache hibernate fonctionne. Une fois la première requête terminée, hibernatez l'entité trouvée dans le cache. La prochaine fois que vous vérifierez, le cache sera vérifié pour voir s'il y a une entité avec l'ID correspondant. S'il y en a, il sera supprimé directement, sinon la requête de la base de données sera réalisée.
Modifions le code à:
User user = (utilisateur) session.load (user.class, new long (29)); System.out.println (user.getName ()); session.evict (utilisateur); // Supprimer l'utilisateur de Cache User User2 = (utilisateur) session.load (user.class, new Long (29)); System.out.println (user2.getName ()); session.close ();
Voir les résultats:
Hibernate: sélectionnez user0_.user_id en tant qu'utilisateur1_0_0_, user0_.user_name en tant qu'utilisateur2_0_0_, user0_.age en tant qu'âge 00_0_ de l'utilisateur user0_ où user0_.user_id =? shun123123 hibernate: sélectionnez user0_.user_id en tant qu'User1_0_0_, user0_.user_name en tant qu'User2_0_, user0_.age en tant qu'âge 00_0_ de l'utilisateur user0_ où user0_.user_id =? shun123123
Après avoir supprimé l'utilisateur du cache, la deuxième requête est également directement récupérée de la base de données.
Talk de cache de niveau 2
Regardons d'abord le cours d'entité:
La classe publique utilisateur implémente Serializable {public long id; nom de chaîne privé; Âge privé; } Le fichier de mappage est omis, tout le monde devrait l'écrire.
Jetons un coup d'œil au fichier de configuration Hibernate:
<propriété name = "hibernate.cache.provider_class"> org.hibernate.cache.ehcacheprovider </ propriété> <propriété name = "Hibernate.cache.use_second_level_cache"> true </ propriété </ propriété Name = "hibernate.cache.use_quey_cache"> true </ propriété>
Nous voyons que dans le provider_class, nous spécifions l'Ehcache, nous avons donc également besoin d'Ehcache.xml pour être placé dans le chemin de classe:
<? xml version = "1.0" coding = "utf-8"?> <ehcache> <diskstore path = "java.io.path" /> <defaultCache maxElementsInMemory = "10000" eternal = "false" timetoidleseconds = "120" timetoliveds = "120" overflowtodisk = "true" /> </ ehcache> "120" overflowtodkis
Ensuite, jetons un coup d'œil à la méthode de test:
public static void main (String [] args) {configuration cfg = new configuration (). configure (); SessionFactory SessionFactory = cfg.BuildSessionFactory (); Session Session = SessionFactory.OpenSession (); Query query = session.CreateeQuery ("de l'utilisateur utilisateur où name = 'shun123'"); Iterator iter = query.iterate (); while (iter.hasnext ()) {System.out.println (((user) iter.next ()). getName ()); } session.close (); Session Session2 = SessionFactory.OpenSession (); Query Query2 = Session2.CreateeQuery ("de l'utilisateur utilisateur où name = 'shun123'"); Iterator iter2 = query2.iterate (); while (iter2.hasnext ()) {System.out.println (((user) iter2.next ()). getName ()); } session2.close (); } Après avoir coulé, vous pouvez voir:
Hibernate: sélectionnez user0_.user_id en tant que col_0_0_ de l'utilisateur user0_ où user0_.user_name = 'shun123' hibernate: sélectionnez user0_.user_id en tant qu'utilisateur1_0_0_, user0_.user_name comme user2_0_.user_.age comme Âge0_0_ à partir de l'utilisateur user0_ où user0_.user_id =? shun123 hibernate: sélectionnez user0_.user_id en tant que col_0_0_ de l'utilisateur user0_ où user0_.user_name = 'shun123' shun123
Nous pouvons voir qu'il effectue une seule phrase de recherche, et l'ID n'est pas récupéré pour la recherche sur la deuxième requête, qui est principalement due au cache secondaire.
Analysons d'abord le code dans la méthode de test. Dans la méthode de test, nous ouvrons deux sessions et créons deux requêtes séparément pour la même requête. Cependant, les deux sessions peuvent partager le cache, qui est le cache de deuxième niveau, le cache de niveau SessionFactory. Tant que notre session est créée par la même sessionFactory, nous pouvons partager le cache secondaire pour réduire l'interaction avec la base de données.
Jetons un coup d'œil à la signification du fichier de configuration:
<propriété name = "hibernate.cache.provider_class"> org.hibernate.cache.ehcacheprovider </ propriété> <propriété name = "Hibernate.cache.use_second_level_cache"> true </ propriété </ propriété Name = "hibernate.cache.use_quey_cache"> true </ propriété>
Si nous devons utiliser le cache secondaire, nous devons d'abord le configurer:
<propriété name = "hibernate.cache.use_second_level_cache"> true </ propriété>
Effectuez le cache d'ouverture du compte de deuxième niveau, puis passez:
<propriété name = "hibernate.cache.provider_class"> org.hibernate.cache.ehcacheprovider </ propriété>
Spécifiez la classe de provision pour le cache secondaire. Généralement, nous utilisons ehcache. Les autres miens ne sont pas utilisés pour le moment et ne sont pas très clairs, donc je n'en parlerai pas pour le moment.
Comme notre exemple tout à l'heure, nous n'avons qu'à configurer les deux ci-dessus, qui peuvent complètement s'exécuter normalement et utiliser le cache secondaire.
Alors, à quoi sert la troisième phrase?
<propriété name = "hibernate.cache.use_query_cache"> true </ propriété>
Cette configuration indique que nous devons utiliser du cache lors de la requête. Si nous devons l'utiliser, nous devons appeler Query.SetCachable (true) à l'avance pour l'activer.
Regardons le code ensemble (nous n'activerons pas le cache pour l'instant):
public static void main (String [] args) {configuration cfg = new configuration (). configure (); SessionFactory SessionFactory = cfg.BuildSessionFactory (); Session Session = SessionFactory.OpenSession (); Query query = session.CreateeQuery ("de l'utilisateur utilisateur où name = 'shun123'"); List list = query.list (); for (int i = 0; i <list.size (); i ++) {System.out.println (((user) list.get (i)). getName ()); } session.close (); Session Session2 = SessionFactory.OpenSession (); Query Query2 = Session2.CreateeQuery ("de l'utilisateur utilisateur où name = 'shun123'"); List list2 = query2.list (); for (int i = 0; i <list2.size (); i ++) {System.out.println (((user) list.get (i)). getName ()); } session2.close (); } La sortie du résultat ici est:
Hibernate: sélectionnez user0_.user_id en tant qu'User1_0_, user0_.user_name as user2_0_, user0_.age en tant qu'âge 0_ de l'utilisateur 0,3e où user0_.user_name = 'shun123' shun123 Hibernate: Sélectionnez User0_.User_id as user1_0_, user0_. Âge 0_ de l'utilisateur utilisateur0_ où user0_.user_name = 'shun123' shun123
Nous voyons qu'il n'utilise pas le cache car nous utilisons la liste ici, et listez uniquement les écritures et ne lis pas le cache. Il y aura donc deux requêtes ici.
Alors modifions-le:
public static void main (String [] args) {configuration cfg = new configuration (). configure (); SessionFactory SessionFactory = cfg.BuildSessionFactory (); Session Session = SessionFactory.OpenSession (); Query query = session.CreateeQuery ("de l'utilisateur utilisateur où name = 'shun123'"); <span style = "background-Color: #ffffff;"> <span style = "Color: # ff0000;"> query.setCachable (true); </span> </span> list list = query.list (); for (int i = 0; i <list.size (); i ++) {System.out.println (((user) list.get (i)). getName ()); } session.close (); Session Session2 = SessionFactory.OpenSession (); Query Query2 = Session2.CreateeQuery ("de l'utilisateur utilisateur où name = 'shun123'"); <span style = "Color: # ff0000;"> query2.setCacheable (true); </span> list list2 = query2.list (); for (int i = 0; i <list2.size (); i ++) {System.out.println (((user) list.get (i)). getName ()); } session2.close (); } J'ai vu deux phrases rouges de code. Ce sont les deux codes que nous avons ajoutés pour activer le cache de requête. Maintenant, nous voyons le résultat:
HiberNate: sélectionnez user0_.user_id comme user1_0_, user0_.user_name en tant qu'utilisateur2_0_, user0_.age en tant qu'âge de 0,e user0_ user0_.user_name = 'shun123' shun123 shun123
Il ne reste plus qu'une requête, pourquoi? Juste à ces deux codes rouges, nous avons allumé le cache, rappelez-vous, il doit être utilisé deux fois. Définissez les deux caches de requête à cache.
Les critères sont également une approche similaire. Afin d'éviter que certaines chaussures d'enfants oublient comment écrire des critères, je vais mettre du code:
public static void main (String [] args) {configuration cfg = new configuration (). configure (); SessionFactory SessionFactory = cfg.BuildSessionFactory (); Session Session = SessionFactory.OpenSession (); Critères critères1 = session.CreateCriteria (user.class); critères1.setCacheable (true); critères1.add (restrictions.eq ("nom", "shun123")); List list = critère1.list (); for (int i = 0; i <list.size (); i ++) {System.out.println (((user) list.get (i)). getName ()); } session.close (); Session Session2 = SessionFactory.OpenSession (); Critères critères2 = session2.CreateCriteria (user.class); Critères2.SetCacheable (vrai); critères2.add (restrictions.eq ("nom", "shun123")); List list2 = critères2.list (); for (int i = 0; i <list2.size (); i ++) {System.out.println (((user) list.get (i)). getName ()); } session2.close (); } Voyons les résultats:
HiberNate: sélectionnez this_.user_id comme user1_0_0_, this_.user_name as user2_0_0_, this_.age en tant qu'âge 00_0_ de l'utilisateur this_ où ce_.user_name =? shun123 shun123