Heim  >  Artikel  >  Java  >  Was sind Java Mybatis First-Level-Cache und Second-Level-Cache?

Was sind Java Mybatis First-Level-Cache und Second-Level-Cache?

王林
王林nach vorne
2023-04-25 14:10:141633Durchsuche

I. Was ist ein Cache? Cache ist ein Bereich zum Speichern von Daten im Speicher. Der Zweck besteht darin, die Effizienz der Abfrage zu verbessern. MyBatis speichert die Abfrageergebnisse im Cache. Wenn dasselbe SQL das nächste Mal ausgeführt wird, wird nicht auf die Datenbank zugegriffen, sondern die Ergebnisse werden direkt aus dem Cache abgerufen, wodurch der Druck auf den Server verringert wird.

Was ist Cache?

Ein Datenelement, das im Speicher vorhanden ist.

Was macht der Cache?

Reduzieren Sie die Interaktion zwischen Programm und Datenbank, verbessern Sie die Abfrageeffizienz und verringern Sie den Druck auf Server und Datenbank.

Welche Art von Daten werden zwischengespeichert?

Daten, die häufig abgefragt, aber nicht häufig geändert werden, und Änderungen, die nur geringe Auswirkungen auf die Ergebnisse haben.

Welche Kategorien gibt es im MyBatis-Cache?

Cache der ersten Ebene und Cache der zweiten Ebene

Wie kann man beurteilen, ob zwei SQL gleich sind?

Die SQL-Anweisungen der Abfrage sind dieselben, die übergebenen Parameterwerte sind dieselben, die Anforderungen für die Ergebnismenge sind dieselben und die vorkompilierten Vorlagen-IDs sind dieselben

2 Mabtis First-Level-Cache

Der First-Level-Cache von MyBatis wird auch als lokaler Cache bezeichnet. Das SqlSession-Objekt enthält ein Executor-Objekt, und das Executor-Objekt enthält ein PerpetualCache-Objekt, das Cache-Daten der ersten Ebene speichert.

Da sich der Cache der ersten Ebene im SqlSession-Objekt befindet, kann der Cache der ersten Ebene nur gemeinsam genutzt werden, wenn dasselbe SqlSession-Objekt zum Betreiben der Datenbank verwendet wird.

Der First-Level-Cache von MyBatis ist standardmäßig aktiviert und erfordert keine Konfiguration.

Wie in der folgenden Abbildung gezeigt:

(1) Testen Sie den Cache der ersten Ebene

Was sind Java Mybatis First-Level-Cache und Second-Level-Cache?Tatsächlich ist die Testmethode sehr einfach, nämlich durch die Verwendung derselben und unterschiedlicher SqlSession-Objekte Um SQL-Abfragen durchzuführen, können Sie anhand des Hashs des zurückgegebenen Objekts feststellen, ob die Werte gleich sind. Wenn die zurückgegebenen Hash-Werte gleich sind, bedeutet dies, dass keine SQL-Abfrage ausgeführt wird, sondern das Objekt direkt zurückgegeben wird Im Folgenden wird dasselbe Sitzungsobjekt zum Ausführen der Abfrage verwendet. Wenn Sie beobachten, dass der Hashwert von Benutzer2 identisch ist, bedeutet dies, dass der Cache der ersten Ebene tatsächlich aktiviert ist und keine Abfrage ausgeführt wird. Die Daten werden jedoch direkt aus dem Cache bezogen.

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();
    }
}

Ausführungsergebnisse

OK, tatsächlich sind die zurückgegebenen Hash-Werte dieselben, und wir können durch die Konsolenausgabe zeigen, dass keine Abfrage erfolgt, sondern das Objekt direkt aus dem Cache abgerufen und zurückgegeben wird Dies ist also der Cache der ersten Ebene, der die Abfrageeffizienz verbessert. F Unten verwenden Sie verschiedene SQL-Sessions, um zu testen, ob der zurückgegebene Hash-Wert konsistent ist Aus der Steuerung und der Steuerung aus der Steuerung ist auch ersichtlich, dass hier tatsächlich eine Abfrage durchgeführt wurde, sodass bestätigt werden kann, dass der gemeinsam genutzte Cache der ersten Ebene tatsächlich auf dem SqlSession-Objekt basiert

(2) Leeren Sie den Cache der ersten Ebene

Was sind Java Mybatis First-Level-Cache und Second-Level-Cache?

Wenn jedoch zu viele zwischengespeichert wurden, wirkt sich dies auch auf unsere Abfrageeffizienz aus. Daher müssen wir den Cache zu diesem Zeitpunkt löschen, genau wie wir es müssen Leeren Sie den Cache des Mobiltelefons von Zeit zu Zeit, da er sonst sehr hängen bleibt. Aus dem gleichen Grund. Wie löscht man den Cache der ersten Ebene?

Führen Sie die folgenden Vorgänge aus, um den MyBatis-Cache der ersten Ebene zu löschen:

SqlSession-Aufruf close(): Nach dem Vorgang ist das SqlSession-Objekt nicht verfügbar und die zwischengespeicherten Daten des Objekts sind ebenfalls nicht verfügbar.

Was sind Java Mybatis First-Level-Cache und Second-Level-Cache?SqlSession ruft clearCache() / commit() auf: Der Vorgang löscht die Cache-Daten der ersten Ebene.

SqlSession Rufen Sie die Methode zum Hinzufügen, Löschen und Ändern auf: Der Vorgang löscht die Cache-Daten der ersten Ebene, da sich die Datenbank nach dem Hinzufügen, Löschen und Ändern ändert und die zwischengespeicherten Daten ungenau sind

// 测试使用不同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();
    }

Ausführung Wirkung

    OK, return Die Hash-Werte sind zwar unterschiedlich, aber haben wir beobachtet, dass bei der Verwendung verschiedener SqlSession-Objekte zum Ausführen der oben genannten Abfragen die Konsoleneingabeanzeige etwas anders ist, das heißt, es gibt keine Hier muss eine JDBC-Verbindung hergestellt werden, was auch die Abfrageeffizienz effektiv verbessert, sodass wir den Cache immer noch gelegentlich leeren müssen

三、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());
}

运行结果 

Was sind Java Mybatis First-Level-Cache und Second-Level-Cache?

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

Das obige ist der detaillierte Inhalt vonWas sind Java Mybatis First-Level-Cache und Second-Level-Cache?. Für weitere Informationen folgen Sie bitte anderen verwandten Artikeln auf der PHP chinesischen Website!

Stellungnahme:
Dieser Artikel ist reproduziert unter:yisu.com. Bei Verstößen wenden Sie sich bitte an admin@php.cn löschen