First, Mybatis cache

  • Like most ORM layer frameworks, Mybatis naturally provides support for level 1 and level 2 caches.

Level 1 cache is the SqlSession level cache. The sqlSession object is constructed when the database is manipulated, and there is a (memory area) data structure (HashMap) in the object to store cached data. The cache data area (HashMap) between different SQLsessions does not affect each other.

Level 2 cache is mapper level cache, multiple SQLSessions to operate the same MAPper SQL statement, multiple SQLsessions to operate the database data will exist level 2 cache area, multiple SQLsessions can share level 2 cache, level 2 cache is cross-SQLSESSION.

The scope of level 1 cache is the same SqlSession. When the same SQL statement is executed twice in the same SqlSession, the data queried in the database will be written to the cache (memory) after the first execution, and the data will be obtained from the cache and will not be queried from the database for the second time, thus improving the query efficiency. When a sqlSession ends, the level 1 cache in that sqlSession ceases to exist. Mybatis enables level 1 caching by default.

Level 2 cache is shared by multiple SQLSessions, whose scope is the same namespace of Mapper. Different SQLsessions execute the SQL statement of the same namespace twice and pass the same parameters to THE SQL, that is, execute the same SQL statement. After the first execution, the data queried in the database will be written to the cache (memory). After the second execution, the data will be obtained from the cache and will not be queried from the database, thus improving the query efficiency. Level 2 caching is disabled in Mybatis by default. You need to configure level 2 caching in setting.

 

2, Redis management Mybatis level 2 cache implementation (Spring Boot project)

1. Introduce dependencies

    <! - introduce jedis -- -- >
    <dependency>
       <groupId>redis.clients</groupId>
       <artifactId>jedis</artifactId>
    </dependency>

    <! -- Introducing a toolkit -->
    <dependency>
      <groupId>org.apache.commons</groupId>
      <artifactId>commons-lang3</artifactId>
      <version>3.4</version>
    </dependency>
Copy the code

2. Write the configuration in application.yml

server:
  port: 8081
spring: session: store-type: redis # Specifies that redis is used to store session informationredisSpecifies information about the Redis serverhost: 192.168174.128.
    port: 6379
Copy the code

3. Implement the Cache interface of Mybatis to complete the custom Cache

package com.baizhi.cache;

import org.apache.commons.lang3.SerializationUtils;
import org.apache.ibatis.cache.Cache;
import org.apache.ibatis.cache.CacheException;
import redis.clients.jedis.Jedis;

import java.io.Serializable;
import java.util.concurrent.locks.ReadWriteLock;

public class RedisCache implements Cache {


    private final String id;

    private Jedis cache = new Jedis("192.168.174.128".6379);

    public RedisCache(String id) {
        this.id = id;
    }

    @Override
    public String getId(a) {
        return id;
    }

    @Override
    // Returns the number of all key/value pairs cached
    public int getSize(a) {
        Long dbSize = cache.dbSize();
        return dbSize.intValue();
    }

    @Override
    // Store data to the cache
    public void putObject(Object key, Object value) {
        System.out.println("key:"+key);
        // Serialize objects as byte arrays into the Commens-Lang3 toolkit
        byte[] keyBs = SerializationUtils.serialize((Serializable) key);
        byte[] valueBs = SerializationUtils.serialize((Serializable) value);

        cache.set(keyBs, valueBs);
    }

    @Override
    // Retrieve data from the cache
    public Object getObject(Object key) {
        byte[] keyBs = SerializationUtils.serialize((Serializable) key);
        byte[] valueBs = cache.get(keyBs);
        if(valueBs ! =null) { // The first time the cache looks for data, it returns null
            return SerializationUtils.deserialize(valueBs);
        }
        return null;
    }

    @Override
    // Clear the cache
    public Object removeObject(Object key) {
        // Get the deleted object
        byte[] keyBs = SerializationUtils.serialize((Serializable) key);
        byte[] valueBs = cache.get(keyBs);
        Object obj = SerializationUtils.deserialize(valueBs);
        cache.del(keyBs);// Perform the delete operation
        return obj;
    }

    @Override
    // Clear the cache
    public void clear(a) {
        cache.flushDB();
    }

    @Override
    public ReadWriteLock getReadWriteLock(a) {
        return null;
    }

    @Override
    public boolean equals(Object o) {
        if (getId() == null) {
            throw new CacheException("Cache instances require an ID.");
        }
        if (this == o) {
            return true;
        }
        if(! (oinstanceof Cache)) {
            return false;
        }

        Cache otherCache = (Cache) o;
        return getId().equals(otherCache.getId());
    }

    @Override
    public int hashCode(a) {
        if (getId() == null) {
            throw new CacheException("Cache instances require an ID.");
        }
        returngetId().hashCode(); }}Copy the code

You can modify this by pasting the PrepetualCache method in idea with CTRL + T

4. Use custom caches in Mybatis

<! Use custom level 2 cache -->
<cache type="com.xxxx.cache.RedisCache"></cache>
Copy the code

5. Enable mybatis level 2 cache in the Springboot project

mybatis:
  mapper-locations: classpath:com/xxxx/mapper/* mapper. XML type-aliases-package: com.xxxx.entity Configuration: # Enable mybatis secondary cache cache-enabled: trueCopy the code

6. After writing the DAO Service Controller layer, start the test

  • controller
package com.baizhi.controller;

import com.baizhi.entity.User;
import com.baizhi.service.UserService;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;

import javax.servlet.http.HttpSession;
import java.util.List;

@RestController
@RequestMapping("user")
public class UserController {

    @Autowired
    private UserService userService;

    @RequestMapping("findAll")
    public List<User> findAll(a){
        List<User> users = userService.findAll();
        returnusers; }}Copy the code
  • Browser enter localhost: 8081 / user/the.findall, appeared the following result

  • The key obtained in the pushObject method:

          key:514810625:3350643160:com.xxxx.dao.UserDAO.findAll:0:2147483647:select * from t_user:SqlSessionFactoryBean

  • Redis library has been cached:

 

 

After one access, a second access will fetch the data from the cache, which becomes very fast, especially when there is a large amount of data.

Note: The entity class must implement the Serializable interface