O princípio e uso dos caches primário e secundário de Mybatis, a proibição de métodos especificados de cache secundário e cache de atualização, integração de Mybatis do Ehcache, os cenários de uso e limitações do cache secundário-day03

A primeira seção Mybatis cache

1.1 Compreensão do cache Mybatis

  • O cache do Mybatis é semelhante ao cache do hibernate, incluindo o cache de primeiro nível e o cache de segundo nível.O cache de primeiro nível é usado por padrão, e o cache de segundo nível precisa ser ativado manualmente.
  • O cache de primeiro nível refere-se a sqlsession. Há uma área de dados em sqlsession, que é uma estrutura de mapa. Esta área é a área de cache de primeiro nível. A chave no cache de primeiro nível é um valor exclusivo composto de informações como instruções, condições e instruções SQL. O valor no cache de primeiro nível é o objeto de resultado da consulta.
  • O cache de segundo nível se refere ao mapeador sob o mesmo namespace. No cache de segundo nível, há também uma estrutura de mapa. Esta área é a área de cache de primeiro nível.
    Insira a descrição da imagem aqui

Obtenha alguns dados em sqlSession1 e poderá obter os mesmos dados em sqlSession2 sem usar SQL. Neste momento, você precisa usar o cache secundário.
O cache secundário é compartilhado por todas as sqlSessions

1.2 Cache de nível 1

princípio

  • A primeira consulta para um usuário cujo id é 1 executará sql, e o cache de primeiro nível será executado por padrão, e os dados serão armazenados no cache de primeiro nível Map. Quando a modificação, adição e exclusão de usuários forem enviadas, o cache de primeiro nível será limpo. , Consulte o usuário cujo id é 1 novamente e precisa executar o sql novamente
    Insira a descrição da imagem aqui

Use e teste

  • Métodos save e findUserById anteriores
    Insira a descrição da imagem aqui
    Insira a descrição da imagem aqui
  • Observe que a classe a ser configurada para implementar a interface de serialização (ou seja, um sinalizador serializável), caso contrário, um erro será relatado
    Insira a descrição da imagem aqui

Insira a descrição da imagem aqui

	@Test
    public void test1() throws IOException {
    
    
        //1.读取配置文件
        InputStream inputStream = Resources.getResourceAsStream("SqlMapConfig.xml");
        //2.通过SqlSessionFactoryBuilder创建SqlSessionFactory会话工厂
        SqlSessionFactory sessionFactory = new SqlSessionFactoryBuilder().build(inputStream);
        //3.通过SqlSessionFactory创建SqlSession
        SqlSession sqlSession = sessionFactory.openSession();

        //默认情况下的一级缓存是开启的
        //4.通过会话获取dao接口
        UserMapper userMapper = sqlSession.getMapper(UserMapper.class);

        User user1 = userMapper.findUserById(1);
        System.out.println(user1);

        //第二次不会执行sql
        User user2 = userMapper.findUserById(1);
        System.out.println(user2);

        sqlSession.close();
    }
  • Quando envolve salvar, atualizar, excluir, etc., o cache de primeiro nível é automaticamente limpo
    Insira a descrição da imagem aqui
	@Test
    public void test2() throws IOException {
    
    
        //1.读取配置文件
        InputStream inputStream = Resources.getResourceAsStream("SqlMapConfig.xml");
        //2.通过SqlSessionFactoryBuilder创建SqlSessionFactory会话工厂
        SqlSessionFactory sessionFactory = new SqlSessionFactoryBuilder().build(inputStream);
        //3.通过SqlSessionFactory创建SqlSession
        SqlSession sqlSession = sessionFactory.openSession();

        //默认情况下的一级缓存是开启的
        //保存、删除、更新后,一级缓存会自动清空,下次查询会再次执行sql
        //4.通过会话获取dao接口
        UserMapper userMapper = sqlSession.getMapper(UserMapper.class);

        User user1 = userMapper.findUserById(1);
        System.out.println(user1);

        //保存一个新用户
        userMapper.save(new User("shu1","男",new Date(),"北京市"));
        //若要保存到数据库记得提交事务,否则不影响数据库,这里只做演示一级缓存可不提交
        sqlSession.commit();
        //此时第二次会执行sql
        User user2 = userMapper.findUserById(1);
        System.out.println(user2);

        sqlSession.close();
    }

Insira a descrição da imagem aqui

1.3 cache secundário

princípio

Insira a descrição da imagem aqui

Use e teste

  1. Ligue a chave geral do cache secundário (configurado no arquivo de configuração global) (mais configurações são definidas no dia01)
    Insira a descrição da imagem aqui
  2. Configure o cache secundário em UserMapper.xml
    Insira a descrição da imagem aqui
  3. teste
  • Observe que a classe a ser configurada para implementar a interface de serialização (ou seja, um sinalizador serializável), caso contrário, um erro será relatado
    Insira a descrição da imagem aqui
    Insira a descrição da imagem aqui
	//二级缓存
    @Test
    public void test3() throws IOException {
    
    
        //1.读取配置文件
        InputStream inputStream = Resources.getResourceAsStream("SqlMapConfig.xml");
        //2.通过SqlSessionFactoryBuilder创建SqlSessionFactory会话工厂
        SqlSessionFactory sessionFactory = new SqlSessionFactoryBuilder().build(inputStream);
        //3.通过SqlSessionFactory创建SqlSession
        SqlSession sqlSession1 = sessionFactory.openSession();
        SqlSession sqlSession2 = sessionFactory.openSession();

        //默认情况下的一级缓存是开启的
        //保存、删除、更新后,一级缓存会自动清空,下次查询会再次执行sql
        //4.通过会话获取dao接口
        UserMapper userMapper1 = sqlSession1.getMapper(UserMapper.class);
        UserMapper userMapper2 = sqlSession2.getMapper(UserMapper.class);


        User user1 = userMapper1.findUserById(1);
        System.out.println(user1);
        //session关闭了,数据才会写入二级缓存
        sqlSession1.close();

        User user2 = userMapper2.findUserById(1);
        System.out.println(user2);
        sqlSession2.close();
    }
  1. Se operações como inserir, atualizar, excluir, etc. forem realizadas, o cache secundário será limpo
	@Test
    public void test4() throws IOException {
    
    
        //1.读取配置文件
        InputStream inputStream = Resources.getResourceAsStream("SqlMapConfig.xml");
        //2.通过SqlSessionFactoryBuilder创建SqlSessionFactory会话工厂
        SqlSessionFactory sessionFactory = new SqlSessionFactoryBuilder().build(inputStream);
        //3.通过SqlSessionFactory创建SqlSession
        SqlSession sqlSession1 = sessionFactory.openSession();
        SqlSession sqlSession2 = sessionFactory.openSession();
        SqlSession sqlSession3 = sessionFactory.openSession();

        //默认情况下的一级缓存是开启的
        //保存、删除、更新后,一级缓存会自动清空,下次查询会再次执行sql
        //4.通过会话获取dao接口
        UserMapper userMapper1 = sqlSession1.getMapper(UserMapper.class);
        UserMapper userMapper2 = sqlSession2.getMapper(UserMapper.class);
        UserMapper userMapper3 = sqlSession3.getMapper(UserMapper.class);

        User user1 = userMapper1.findUserById(1);
        System.out.println(user1);
        sqlSession1.close();

        //保存用户,二级缓存也会清空
        userMapper3.save(new User("shu2","男",new Date(),"上海市"));
        sqlSession3.commit();
        sqlSession3.close();

        User user2 = userMapper2.findUserById(1);
        System.out.println(user2);
        sqlSession2.close();

    }

Insira a descrição da imagem aqui
Insira a descrição da imagem aqui

Desativa o cache de segundo nível do método especificado

Insira a descrição da imagem aqui

  • O cache de segundo nível do método especificado é desabilitado, o cache de segundo nível deste método não tem efeito e outros métodos não afetam
    Insira a descrição da imagem aqui

Atualizar cache

  • O cache de segundo nível do método especificado está desativado acima. Este método é usado para refletir o cache de segundo nível. Lembre-se de remover a desativação, caso contrário, o cache não será atualizado.
    Insira a descrição da imagem aqui
    Insira a descrição da imagem aqui

Resumindo

O ponto comum entre o cache de primeiro nível e o cache de segundo nível: quando operações como inserir, atualizar e excluir são realizadas, o cache é limpo.

1.4 Integrar ehcache

  • Pergunta: Por que não usar o cache que vem com o Mybatis, mas integrar o cache ehcache?
  • Resposta: Mybatis em si é uma estrutura de camada de persistência, não é uma estrutura de cache dedicada, então sua implementação de cache não é boa o suficiente para suportar distribuído, enquanto Ehcache é uma estrutura de cache distribuída.

O que é distribuído

  • A fim de melhorar o desempenho, o sistema geralmente adota implantação distribuída (implantação de cluster)
    Insira a descrição da imagem aqui

Pensamento integrado

  • O cache possui uma interface padronizada Cache (para quem deseja utilizá-la basta implementá-la e escrever o método correspondente), e sua implementação padrão é PerpetualCache de mybatis. Se você deseja integrar o cache secundário de mybatis, implemente a interface do Cache.
    Insira a descrição da imagem aqui
  • Mybatis vem com cache de implementação
    Insira a descrição da imagem aqui

Etapas de integração

Etapa 1: importe o pacote jar

Insira a descrição da imagem aqui
Insira a descrição da imagem aqui

  • Você pode ver o cache implementado pelo ehcache
    Insira a descrição da imagem aqui

Etapa 2: configurar a tag de cache no arquivo de mapeamento

Insira a descrição da imagem aqui

	<!--配置缓存
    type不写,默认使用的就是mybatis自带的缓存技术,perpetualCache永久缓存
    -->
    <cache type="org.mybatis.caches.ehcache.EhcacheCache"></cache>

Etapa 3: adicionar o arquivo de configuração ehcache em src

Insira a descrição da imagem aqui

  • Copie-o para o diretório src e renomeie-o para ehcache.xml (após excluir o comentário)
    Insira a descrição da imagem aqui

  • maxElementsInMemory: Defina o número máximo de objetos que podem ser armazenados no cache baseado em memória.

  • eterno: Defina se o objeto é permanente, verdadeiro significa nunca expirar; se for falso, deve ser julgado de acordo com timeToIdleSeconds e timeToLiveSeconds.

  • timeToIdleSeconds: Defina o tempo máximo para o objeto ficar ocioso, em segundos. Após este tempo, o objeto expira. Quando o objeto expira, o EHCache o remove do cache. Se este valor for 0, significa que o objeto pode ficar inativo indefinidamente. (A unidade é segundos)

  • timeToLiveSeconds: Defina o tempo máximo de vida do objeto. Após esse tempo, o objeto expira. Se este valor for 0, significa que o objeto pode existir no cache indefinidamente. O valor do atributo deve ser maior ou igual ao valor do atributo timeToIdleSeconds (em segundos)

  • overflowToDisk: Defina se deseja gravar objetos de estouro no cache baseado em disco rígido depois que o número de objetos no cache interno atingir o limite superior

  • diskPersistent: se deve persistir o objeto (armazenado no disco rígido) quando o jvm termina, verdadeiro ou falso é opcional, o padrão é falso

  • diskExpiryThreadIntervalSeconds: Especifica o tempo de polling do thread de escuta dedicado à limpeza de objetos expirados. (A unidade é segundos)

  • memoryStoreEvictionPolicy: Quando o cache de memória atinge o máximo e um novo elemento é adicionado, a política quando o elemento no cache é removido para o disco. O padrão é LRU (menos usado recentemente), as opções são LFU (menos usado, menos usado) e FIFO (primeiro a entrar, primeiro a sair)

  • LRU (menos usado recentemente): o elemento em cache tem um carimbo de data / hora. Quando a capacidade do cache estiver cheia e você precisar criar espaço para armazenar novos elementos em cache, o elemento no elemento de cache existente cujo carimbo de data / hora é o mais distante da hora atual Será apagado do cache.

  • LFU (usado com menos frequência): o elemento armazenado em cache tem um atributo de ocorrência e aquele com o menor valor de ocorrência será limpo do cache.

Etapa 4: teste

  • Use o cache secundário de teste anterior
	//二级缓存
    @Test
    public void test3() throws IOException {
    
    
        //1.读取配置文件
        InputStream inputStream = Resources.getResourceAsStream("SqlMapConfig.xml");
        //2.通过SqlSessionFactoryBuilder创建SqlSessionFactory会话工厂
        SqlSessionFactory sessionFactory = new SqlSessionFactoryBuilder().build(inputStream);
        //3.通过SqlSessionFactory创建SqlSession
        SqlSession sqlSession1 = sessionFactory.openSession();
        SqlSession sqlSession2 = sessionFactory.openSession();

        //默认情况下的一级缓存是开启的
        //保存、删除、更新后,一级缓存会自动清空,下次查询会再次执行sql
        //4.通过会话获取dao接口
        UserMapper userMapper1 = sqlSession1.getMapper(UserMapper.class);
        UserMapper userMapper2 = sqlSession2.getMapper(UserMapper.class);

        User user1 = userMapper1.findUserById(1);
        System.out.println(user1);
        //session关闭了,数据才会写入二级缓存
        sqlSession1.close();

        User user2 = userMapper2.findUserById(1);
        System.out.println(user2);
        sqlSession2.close();
    }
  • Execute SQL uma vez e busque-o do cache de segundo nível pela segunda vez
    Insira a descrição da imagem aqui

1.5 Cenários de uso de cache secundário

  • Para consultas que requerem alta velocidade de resposta de acesso, mas baixo desempenho em tempo real, a tecnologia de cache secundário pode ser usada .
    Observação: ao usar o cache de segundo nível, você deve definir um intervalo de atualização (há um atributo flashInterval na tag de cache) para atualizar o cache de segundo nível regularmente. Este intervalo de atualização é definido de acordo com necessidades específicas, como 30 minutos, 60 minutos, etc., unidade São milissegundos.
  • Por exemplo: defina o intervalo de atualização do cache para 60 minutos (limpe o cache a cada 60 minutos)
    Insira a descrição da imagem aqui

1.6 Limitações do cache de segundo nível

  • O cache de segundo nível Mybatis não é bem implementado para dados de baixa granularidade.

  • Por exemplo: Cache de informações do produto. Devido à grande quantidade de visitas de consulta de informações do produto, os usuários devem consultar as informações mais recentes do produto todas as vezes. Neste momento, se o cache secundário for usado, é impossível atualizar apenas as informações do produto em cache quando um produto muda. Ele não atualiza outras informações do cache do produto, porque o cache secundário está no nível do mapeador. Quando as informações de um produto são atualizadas, os dados do cache de informações de todos os produtos serão apagados.

  • Para resolver esses problemas, os dados precisam ser armazenados em cache de maneira direcionada na camada de negócios, conforme necessário.

  • Por exemplo, as operações de alteração frequente de dados podem ser colocadas separadamente no mapeador de outro namespace.

Acho que você gosta

Origin blog.csdn.net/qq_43414199/article/details/108883820
Recomendado
Clasificación