Maison  >  Article  >  Java  >  Explication détaillée du cache de requêtes MyBatis en Java

Explication détaillée du cache de requêtes MyBatis en Java

怪我咯
怪我咯original
2017-06-30 10:57:301443parcourir

L'utilisation du cache de requêtes vise principalement à améliorer la vitesse d'accès aux requêtes. Cet article présente principalement le cache de requêtes MyBatis. Les amis qui en ont besoin peuvent se référer à l'utilisation du cache de requêtes

, principalement pour améliorer la vitesse d'accès aux requêtes. Simplifiez le processus de requête répétée de l'utilisateur pour les mêmes données, au lieu d'obtenir à chaque fois les données de résultat de la requête de base de données, améliorant ainsi la vitesse d'accès.

Le mécanisme de mise en cache des requêtes de MyBatis peut être divisé en deux types selon l'étendue de la zone de cache (cycle de vie) : cache de premier niveau et cache de deuxième niveau

1. Cache de requêtes de premier niveau

Le cache de premier niveau MyBatis est un cache local HashMap basé sur org.apache.ibatis.cache.impl.PerpetualCache. classe, et sa portée est Sqlsession. Exécutez la même instruction SQL deux fois dans la même session SQL. Après la première exécution, les résultats de la requête seront écrits dans le cache. La deuxième fois, les données seront obtenues directement à partir du cache sans interroger la base de données, améliorant ainsi l'efficacité de la requête.

Lorsqu'une session SQL se termine, le cache de premier niveau de la session SQL n'existe plus. Le cache de premier niveau de MyBatis est activé par défaut et ne peut pas être désactivé.

1. Preuve d'existence du cache de premier niveau

Classe de test :

//证明一级缓存的存在
@Test
public void test01(){
 //第一次查询
 Student student = dao.selectStudentById(2);
 System.out.println(student);
 //第二次查询
 Student student2 = dao.selectStudentById(2);
 System.out.println(student2);  
}

mapper :

<mapper namespace="com.hcx.dao.IStudentDao">  
  <select id=selectStudentById resultType="com.hcx.beans.Student">
   select * from student where id=#{id}
  </select>
</mapper>


Console :

Après l'exécution, il a été constaté qu'une seule requête de la base de données avait été exécutée et le deuxième résultat était directement affiché de. Notez que la deuxième fois est lue depuis le cache Sqlsession.

2. La base de lecture des données du cache est l'identifiant SQL

Le cache de premier niveau met en cache le même SQL. mapping id Les résultats de la requête, plutôt que les résultats de la requête de la même instruction SQL. Étant donné que le cache de requêtes interne de MyBatis, qu'il s'agisse d'une requête de premier niveau ou d'une requête de deuxième niveau, la couche inférieure est implémentée à l'aide d'une hashmap : la clé est le contenu lié à l'identifiant du SQL et la valeur est le résultat de la requête. à partir de la base de données.

mapper :


<mapper namespace="com.hcx.dao.IStudentDao">
  <select id=selectStudentById resultType="com.hcx.beans.Student">
   select * from student where id=#{id}
  </select>
  <select id="selectStudnetById2" resultType="com.hcx.beans.Student">
   select id,name,age,score,birthday from student where id=#{id}
  </select>
</mapper>

interface dao :

public interface IStudentDao {  
 Student selectStudentById(int id);
 Student selectStudentById2(int id); 
}

Classe de test :

//证明从一级缓存中读取数据的依据:
//MyBatis:sql的id+sql语句
//hibernate:查询结果对象的id
@Test
public void test02(){
 Student student = dao.selectStudentById(2);
 System.out.println(student);

 Student student2 = dao.selectStudentById2(2);
 System.out.println(student2);  
}

Console :

Vérifiez la console et constatez que les résultats de la deuxième requête sont exactement les mêmes que la première, mais la deuxième requête ne lit pas les données du cache, mais directement de la base de données. En effet, la base de lecture des données du cache est l'ID de mappage de la requête SQL, et non le résultat de la requête.

3. L'impact des ajouts, suppressions et modifications sur le cache de requêtes de premier niveau

Ajouts, suppressions et modifications, que Sqlsession.commit( ) efface ou non le cache de requêtes de premier niveau afin que la requête puisse être à nouveau sélectionnée dans la base de données.

Classe de test :

@Test
public void test03(){
 Student student = dao.selectStudentById(2);
 System.out.println(student);
 //增删改操作都会清空一级缓存,无论是否提交
 dao.insertStudent(new Student("赵六",26,96.6));
 Student student2 = dao.selectStudentById(2);
 System.out.println(student2);  
}

Console :


2. Secondaire intégré niveau Cache de requêtes

La portée du cache de requêtes MyBatis est divisée en fonction de l'espace de noms du mappeur de fichiers de mappage. Les données de requête du mappeur du même espace de noms sont stockées dans la même zone de cache. Les données dans différents espaces de noms n'interfèrent pas les unes avec les autres.

Le cache de premier niveau et le cache de deuxième niveau sont stockés séparément en fonction de l'espace de noms. Mais la différence entre le cache de premier et de deuxième niveau est qu'une fois la session SQL fermée, les données de la session SQL n'existeront plus, c'est-à-dire que le cache de premier niveau n'existera plus. Le cycle de vie du cache de deuxième niveau sera synchronisé avec l'ensemble de l'application, que la session SQL soit fermée ou non.

Le but de l'utilisation du cache de deuxième niveau n'est pas de partager des données, car MyBatis lit les données du cache en fonction de l'identifiant SQL, et non de l'objet interrogé. Par conséquent, les données du cache de deuxième niveau ne sont pas destinées à être partagées entre plusieurs requêtes (tant que l'objet existe dans les résultats de la requête dans toutes les requêtes, il est lu directement depuis le cache. Il s'agit du partage de données. le cache en veille prolongée est destiné au partage, mais MyBatis ne l'est pas), mais pour prolonger la durée de stockage des résultats de la requête et améliorer les performances du système.

1. Utilisation du cache de deuxième niveau

L'utilisation du cache de deuxième niveau ne nécessite que deux étapes :

Entités sérialisées

Ajouter le e20c50086bb6799ec27a6a73752fc01b dans le fichier de mappage du mappeur

1. La sérialisation d'entité

nécessite que la classe d'entité impliquée dans le résultat de la requête implémente java.io . Interface sérialisable. Si la classe d'entité a une classe parent ou si elle a des attributs de domaine, la classe parent et la classe d'attribut de domaine doivent également implémenter l'interface de sérialisation.

public class Student implements Serializable{
 private Integer id;
 private String name;
 private int age;
 private double score;
}

2. Ajoutez la balise e20c50086bb6799ec27a6a73752fc01b dans le fichier de mappage du mappeur

Ajoutez la balise 707355b79f48ce957b037d12f8d8abdd fichier e20c50086bb6799ec27a6a73752fc01bSub-tag

<mapper namespace="com.hcx.dao.IStudentDao">
 <cache/>
  <select id=selectStudentById resultType="com.hcx.beans.Student">
   select * from student where id=#{id}
  </select>
</mapper>

3. Configuration du cache de deuxième niveau

Ajouter des paramètres d'attributs associés au 6fd13d014b1ccbd154028505911a131c对,即entry对象删除。

从DB中进行select查询的条件是:缓存中根本不存在这个key或者缓存中存在该key所对应的entry对象,但value为null。

设置增删改操作不刷新二级缓存:

若要使某个增、删或改操作不清空二级缓存,则需要在其2fe416ebc99307b5baa877beb4126ed0或f353c4e6f3e13c8cf4dcf649d0662b12或89f2e2a6c0b1bd54a34bdf16f85e8819中添加属性flushCache="false",默认为true。

<insert id="insertStudent" flushCache="false">
  insert into student(name,age,score) values(#{name},#{age},#{score})
 </insert>

4.二级缓存的关闭

二级缓存默认为开启状态。若要将其关闭,则需要进行相关设置。
根据关闭的范围大小,可以分为全局关闭和局部关闭

1.全局关闭(在配置文件中设置)

全局关闭是指整个应用的二级缓存全部关闭,所有查询均不使用二级缓存。全局开关设置在主配置文件的全局设置c5c29794bda4e81a53ad53fcf163f82c中,该属性为cacheEnabled,设置为false,则关闭;设置为true,则开启,默认值为true。即二级缓存默认是开启的。

<!-- 关闭二级缓存 -->
<settings>
 <setting name="cacheEnabled" value="false"/>
</settings>

2.局部关闭(在映射文件的每个select中设置)

局部关闭指整个应用的二级缓存是开启的,但只是针对某个815c08aea17433a6272b681dc1d34168查询,不使用二级缓存。此时可以单独只关闭该815c08aea17433a6272b681dc1d34168标签的二级缓存。

在该要关闭二级缓存的815c08aea17433a6272b681dc1d34168标签中,将其属性useCache设置为false,即可关闭该查询的二级缓存。该属性默认为true,即每个815c08aea17433a6272b681dc1d34168查询的二级缓存默认是开启的。

<!--useCache="false"对当前sql的二级缓存的局部关闭 -->
 <select id=selectStudentById useCache="false" resultType="com.hcx.beans.Student">
  select * from student where id=#{id}
 </select>

5.二级缓存的使用原则

1.只能在一个命名空间下使用二级缓存

由于二级缓存中的数据是基于namespace的,即不同namespace中的数据互不干扰。在多个namespace中若均存在对同一个表的操作,那么这多个namespace中的数据可能就会出现不一致现象。

2.在单表上使用二级缓存

如果一个表与其它表有关联关系,那么久非常有可能存在多个namespace对同一数据的操作。而不同namespace中的数据互补干扰,所以就有可能出现多个namespace中的数据不一致现象。

3.查询多于修改时使用二级缓存

在查询操作远远多于增删改操作的情况下可以使用二级缓存。因为任何增删改操作都将刷新二级缓存,对二级缓存的频繁刷新将降低系统性能。

三、ehcache二级查询缓存

MyBatis允许使用第三方缓存产品。ehCache就是其中一种。

注意:使用ehcache二级缓存,实体类无需实现序列化接口。

1.导入jar包

2.添加ehcache.xml

解压ehcache的核心jar包ehcache-core-2.6.8.jar,将其中的一个配置文件ehcache-failsafe.xml直接放到项目的src目录下,并更名为ehcache.xml

(1)d72dee856555ebc5179da8bdfded1f5b标签

指定一个文件目录,当内存空间不够,需要将二级缓存中数据写到硬盘上时,会写到这个指定目录中。其值一般为java.io.tmpdir,表示当前系统的默认文件临时目录。

当前文件系统的默认文件临时目录,可以通过System.property()方法查看:

@Test
public void test(){
 String path = System.getProperty("java.io.tmpdir");
 System.out.println(path);
}

(2)730eca52cf3beed4d554a3843e167f2e标签

3.启用ehcache缓存机制

在映射文件的mapper中的e20c50086bb6799ec27a6a73752fc01b中通过type指定缓存机制为Ehcache缓存。默认为MyBatis内置的二级缓存org.apache.ibatis.cache.impl.PerpetualCache。

<mapper namespace="com.hcx.dao.IStudentDao">
 <cache type="org.mybatis.caches.ehcache.EhcacheCache"/>
  <select id=selectStudentById resultType="com.hcx.beans.Student">
   select * from student where id=#{id}
  </select>
</mapper>

4.ehcache在不同mapper中的个性化设置

在ehcache.xml中设置的属性值,会对该项目中所有使用ehcache缓存机制的缓存区域起作用。一个项目中可以有多个mapper,不同的mapper有不同的缓存区域。对于不同缓存区域也可进行专门针对于当前区域的个性设置,可通过指定不同mapper的62aecd17e676a41d3547c3bf97bb07b0属性值来设置。

62aecd17e676a41d3547c3bf97bb07b0属性值的优先级高于ehcache.xml中的属性值。

<mapper namespace="com.hcx.dao.IStudentDao">
 <cache type="org.mybatis.caches.ehcache.EhcacheCache"/>
   <property name="maxElementsInMemory" value="5000"/>
   <property name="timeToIdleSeconds" value="240"/>
 </cache>
</mapper>

Ce qui précède est le contenu détaillé de. pour plus d'informations, suivez d'autres articles connexes sur le site Web de PHP en chinois!

Déclaration:
Le contenu de cet article est volontairement contribué par les internautes et les droits d'auteur appartiennent à l'auteur original. Ce site n'assume aucune responsabilité légale correspondante. Si vous trouvez un contenu suspecté de plagiat ou de contrefaçon, veuillez contacter admin@php.cn