Maison  >  Article  >  Java  >  Que sont le cache de premier niveau et le cache de deuxième niveau Java Mybatis ?

Que sont le cache de premier niveau et le cache de deuxième niveau Java Mybatis ?

王林
王林avant
2023-04-25 14:10:141552parcourir

存 存 le cache est une zone où les données sont stockées en mémoire. Le but est d'améliorer l'efficacité des requêtes. MyBatis stockera les résultats de la requête dans le cache lors de la prochaine exécution du même SQL, la base de données ne sera pas accessible, mais les résultats seront obtenus directement à partir du cache, réduisant ainsi la pression sur le serveur.

Qu'est-ce que le cache ?

Une donnée qui existe en mémoire.

À quoi sert le cache ?

Réduisez l'interaction entre le programme et la base de données, améliorez l'efficacité des requêtes et réduisez la pression sur le serveur et la base de données.

Quels types de données sont mis en cache ?

Données fréquemment interrogées mais peu modifiées et modifications ayant peu d'impact sur les résultats.

Quelles sont les catégories du cache MyBatis ?

Cache de premier niveau et cache de deuxième niveau

Comment juger si deux SQL sont identiques ?

Les instructions SQL de la requête sont les mêmes, les valeurs des paramètres transmises sont les mêmes, les exigences pour l'ensemble de résultats sont les mêmes et les ID de modèle précompilés sont les mêmesCache de premier niveau Mabtis

.

Le cache de premier niveau MyBatis est également appelé cache local. L'objet SqlSession contient un objet Executor et l'objet Executor contient un objet PerpetualCache, qui stocke les données du cache de premier niveau.

Étant donné que le cache de premier niveau se trouve dans l'objet SqlSession, le cache de premier niveau ne peut être partagé que lors de l'utilisation du même objet SqlSession pour faire fonctionner la base de données.

Le cache de premier niveau de MyBatis est activé par défaut et ne nécessite aucune configuration.

Comme le montre la figure ci-dessous :

(1) Testez le cache de premier niveau Que sont le cache de premier niveau et le cache de deuxième niveau Java Mybatis ?

En fait, la méthode de test est très simple, c'est-à-dire en utilisant les mêmes objets SqlSession et des objets différents. pour effectuer des requêtes SQL, et le hachage de l'objet renvoyé Vous pouvez savoir si les valeurs sont les mêmes. Si les valeurs de hachage renvoyées sont les mêmes, cela signifie qu'aucune requête SQL n'est effectuée, mais que l'objet est renvoyé directement. à partir du cache. Ce qui suit utilise le même objet Session pour exécuter la requête. Si vous observez user1 et si la valeur de hachage de user2 est la même, cela signifie que le cache de premier niveau est effectivement activé et qu'aucune requête n'est effectuée. mais les données sont obtenues directement à partir du cache.

import com.mybatisstudy.mapper.UserMapper;
import com.mybatisstudy.pojo.User;
import org.apache.ibatis.io.Resources;
import org.apache.ibatis.session.SqlSession;
import org.apache.ibatis.session.SqlSessionFactory;
import org.apache.ibatis.session.SqlSessionFactoryBuilder;
import org.junit.Test;
 
import java.io.InputStream;
 
public class TestUserMapper3 {
    // 测试使用同一个SqlSession查询
    @Test
    public void testCache1() throws Exception{
        InputStream is = Resources.getResourceAsStream("SqlMapConfig.xml");
        SqlSessionFactoryBuilder builder = new SqlSessionFactoryBuilder();
        SqlSessionFactory factory = builder.build(is);
        SqlSession session = factory.openSession();
 
        // 使用同一个SqlSession查询
        UserMapper mapper1 = session.getMapper(UserMapper.class);
        UserMapper mapper2 = session.getMapper(UserMapper.class);
 
        User user1 = mapper1.findById(1);
        System.out.println(user1.hashCode());
        System.out.println("------------------------------------------");
        User user2 = mapper2.findById(1);
        System.out.println(user2.hashCode());
 
        session.close();
    }
}

Résultats de l'exécution

OK, en effet les valeurs de hachage renvoyées sont les mêmes, et nous pouvons montrer à travers la sortie de la console qu'elle n'interroge pas mais récupère l'objet directement depuis le cache et renvoie , il s'agit donc du cache de premier niveau, qui améliore l'efficacité des requêtes. Q Ci-dessous, vous utilisez différentes sessions SQL pour le tester. Si la valeur de hachage renvoyée est cohérente

// 测试使用不同SqlSession查询
    @Test
    public void testCache2() throws Exception{
        InputStream is = Resources.getResourceAsStream("SqlMapConfig.xml");
        SqlSessionFactoryBuilder builder = new SqlSessionFactoryBuilder();
        SqlSessionFactory factory = builder.build(is);
        SqlSession session1 = factory.openSession();
        SqlSession session2 = factory.openSession();
 
        // 测试使用不同SqlSession查询
        UserMapper mapper1 = session1.getMapper(UserMapper.class);
        UserMapper mapper2 = session2.getMapper(UserMapper.class);
 
        User user1 = mapper1.findById(1);
        System.out.println(user1.hashCode());
        System.out.println("---------------------------------");
        User user2 = mapper2.findById(1);
        System.out.println(user2.hashCode());
 
        session1.close();
        session2.close();
    }
E

Que sont le cache de premier niveau et le cache de deuxième niveau Java Mybatis ? Exécuter les résultats

OK, vous pouvez voir que la valeur de hachage renvoyée est différente, et le contrôle du contrôle, et control from control from control. L'affichage de sortie de la station peut également voir qu'une requête a bien été effectuée ici, il peut donc être confirmé que le cache partagé de premier niveau est bien basé sur l'objet SqlSession

(2) Vider le cache de premier niveau

Que sont le cache de premier niveau et le cache de deuxième niveau Java Mybatis ?

Mais, s'il a été mis en cache, s'il y en a trop, cela affectera également l'efficacité de nos requêtes, nous devons donc vider le cache à ce moment-là, tout comme nous devons vider le téléphone mobile cache de temps en temps sinon il sera très bloqué. C'est la même raison. Alors comment vider le cache de premier niveau ?

Effectuez les opérations suivantes pour vider le cache de premier niveau MyBatis :

SqlSession Call close() : Après l'opération, l'objet SqlSession n'est pas disponible, et les données mises en cache de l'objet sont également indisponibles.

SqlSession appelle clearCache() / commit() : l'opération effacera les données du cache de premier niveau.

    SqlSession Appelez la méthode d'ajout, de suppression et de modification : l'opération effacera les données du cache de premier niveau, car la base de données change après l'ajout, la suppression et la modification, les données mises en cache seront inexactes
  • // 清空Mybatis一级缓存
        @Test
        public void testCache3() throws Exception{
            InputStream is = Resources.getResourceAsStream("SqlMapConfig.xml");
            SqlSessionFactoryBuilder builder = new SqlSessionFactoryBuilder();
            SqlSessionFactory factory = builder.build(is);
            SqlSession session = factory.openSession();
     
            UserMapper mapper1 = session.getMapper(UserMapper.class);
            UserMapper mapper2 = session.getMapper(UserMapper.class);
     
            User user1 = mapper1.findById(1);
            System.out.println(user1.hashCode());
     
            // 清空Mybatis一级缓存
            session.clearCache();
     
            System.out.println("-------------------------------");
            User user2 = mapper2.findById(1);
            System.out.println(user2.hashCode());
     
            session.close();
        }
  • Exécution effect

OK, return Les valeurs de hachage sont en effet différentes, mais avons-nous observé que lors de l'utilisation de différents objets SqlSession pour exécuter les requêtes ci-dessus, l'affichage des entrées de la console est un peu différent, c'est-à-dire qu'il n'y a pas nous devons établir une connexion JDBC ici, ce qui améliore également efficacement l'efficacité des requêtes, nous devons donc encore vider le cache de temps en temps

三、Mybatis二级缓存

MyBatis二级缓存也叫全局缓存。数据存放在SqlSessionFactory中,只要是同一个工厂对象创建的SqlSession,在进行查询时都能共享数据。一般在项目中只有一个SqlSessionFactory对象,所以二级缓存的数据是全项目共享的。
MyBatis一级缓存存放的是对象,二级缓存存放的是对象的数据。所以要求二级缓存存放的POJO必须是可序列化的,也就是要实现Serializable接口。
MyBatis二级缓存默认不开启,手动开启后数据先存放在一级缓存中,只有一级缓存数据清空后,数据才会存到二级缓存中。           
SqlSession 调用 clearCache() 无法将数据存到二级缓存中。

(1)开启二级缓存

1. POJO类实现Serializable接口

import java.io.Serializable;
 
public class User implements Serializable {
    private int id;
    private String username;
    private String sex;
    private String address;
}

2. 在Mybatis配置文件添加如下设置

<!-- 二级缓存打开 -->
<settings>   
 <setting></setting>
</settings>

这里有个额外知识,就是Mybatis配置文件的标签还得按照顺序来放的,否则就会以下编译错误;

The content of element type "configuration" must match "(properties?,settings?,typeAliases?,typeHandlers?,objectFactory?,

objectWrapperFactory?,reflectorFactory?,plugins?,environments?,

databaseIdProvider?,mappers?)". 

  同时也说明了放置顺序就得按照match里面的顺序来放

3. 添加 标签

 如果查询到的集合中对象过多,二级缓存只能缓存1024个对象引用。可以通过

标签的size属性修改该数量。

比如:

(2)测试二级缓存

        那怎么测试呢,从上面我们可以知道二级缓存存放的是对象的数据,并且是基于SqlSessionFactory的,因此我们可以用SqlSessionFactory获取两个SqlSession对象,然后让他们分别获取各自的mapper,然后进行查询,返回到同一个实例化的USer对象中,如果返回的数据是一致的,但是对象的哈希值是不一样的话,则说明二级缓存里存放的确实对象的数据而不是对象。

// 测试二级缓存
@Test
public void testCache4() throws Exception {
    InputStream is = Resources.getResourceAsStream("SqlMapConfig.xml");
    SqlSessionFactoryBuilder builder = new SqlSessionFactoryBuilder();
    SqlSessionFactory factory = builder.build(is);
    SqlSession session = factory.openSession();

    UserMapper mapper1 = session.getMapper(UserMapper.class);
    UserMapper mapper2 = session.getMapper(UserMapper.class);

    User user1 = mapper1.findById(1);
    System.out.println(user1);
    System.out.println(user1.hashCode());

    // 让一级缓存失效
    session.commit();
    System.out.println("----------------------------");

    user1 = mapper2.findById(1);
    System.out.println(user1);
    System.out.println(user1.hashCode());
}

运行结果 

Que sont le cache de premier niveau et le cache de deuxième niveau Java Mybatis ?

        OK,从运行结果上我们可以知道结果集返回到同一个对象中,而他们的哈希值反而不一样,说明执行第二次查询的时候新建了一个对象并且该对象指向那个对象并且将SqlSessionFactory中的数据赋值到新建的那个对象。其实从控制台打印的日志我们也可以得出,并没有执行查询方法,因为没有打印SQL语句,而且缓存也是从0.0改成了0.5,因此我们可以断定二级缓存存放的是数据而不是对象。

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:
Cet article est reproduit dans:. en cas de violation, veuillez contacter admin@php.cn Supprimer