mybatis整合 SpringBoot(缓存机制)

有了mybatis公司给我们整合的工具类那么我们就不用像以前还得去配置数据源 我们在这里只需引入依赖即可:

我们首先先创建一个简单的数据库

create database springbootmapper;

CREATE TABLE `user` (
  `id` int(16) unsigned NOT NULL AUTO_INCREMENT,
  `name` varchar(16) NOT NULL,
  `age` int(4) NOT NULL,
  PRIMARY KEY (`id`)
) ENGINE=InnoDB AUTO_INCREMENT=3 DEFAULT CHARSET=utf8

随便插入几条数据:
在这里插入图片描述项目结构
在这里插入图片描述

在创建工程→引入依赖

<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0"
         xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
         xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
    <modelVersion>4.0.0</modelVersion>

    <groupId>com.cs</groupId>
    <artifactId>springBoot_Mybatis</artifactId>
    <version>1.0-SNAPSHOT</version>
    <parent>
        <groupId>org.springframework.boot</groupId>
        <artifactId>spring-boot-starter-parent</artifactId>
        <version>2.1.3.RELEASE</version>
        <relativePath/>
    </parent>
    <dependencies>
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-test</artifactId>
        </dependency>

        <dependency>
            <groupId>org.mybatis.spring.boot</groupId>
            <artifactId>mybatis-spring-boot-starter</artifactId>
            <version>2.0.1</version>
        </dependency>
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-web</artifactId>
        </dependency>
        <dependency>
            <groupId>org.projectlombok</groupId>
            <artifactId>lombok</artifactId>
        </dependency>
        <dependency>
        <groupId>tk.mybatis</groupId>
        <artifactId>mapper-base</artifactId>
            <version>1.1.5</version>
        </dependency>
        <dependency>
            <groupId>tk.mybatis</groupId>
            <artifactId>mapper-core</artifactId>
            <version>1.1.5</version>
        </dependency>
        <dependency>
            <groupId>mysql</groupId>
            <artifactId>mysql-connector-java</artifactId>
            <version>5.1.46</version>
        </dependency>
        <dependency>
            <groupId>tk.mybatis</groupId>
            <artifactId>mapper-extra</artifactId>
            <version>1.1.5</version>
        </dependency>
        <dependency>
            <groupId>tk.mybatis</groupId>
            <artifactId>mapper-spring</artifactId>
            <version>1.1.5</version>
        </dependency>
    </dependencies>

    <build>
        <plugins>
            <plugin>
                <groupId>org.apache.maven.plugins</groupId>
                <artifactId>maven-compiler-plugin</artifactId>
                <configuration>
                    <source>1.8</source>
                    <target>1.8</target>
                </configuration>
            </plugin>
        </plugins>
    </build>
</project>

创建配置文件:
application.yml

server:
  port: 8333  #端口号

mybatis:
  type-aliases-package: com.cs.dto.UserDto  #对应的实体类
  configuration:
    map-underscore-to-camel-case: true
  mapper-locations: mappers/*.xml #如果还想用之前的mapper.xml写sql语句也可以放在这里
spring:
  application:
    name: myTest  
  datasource: #数据源
      driver-class-name: com.mysql.jdbc.Driver
      url: jdbc:mysql://localhost:3306/springbootmapper?characterEncoding=utf8&amp;useSSL=false
      username: root
      password: root

创建与是数据库表对应的实体类(对象关系映射ORM)
UserDto .java

package com.cs.demo.dto;

import lombok.Data;
import tk.mybatis.mapper.annotation.KeySql;
import javax.persistence.Id;
import javax.persistence.Table;

@Data  //lombok注解  自动有 get set 方法
@Table(name = "user")  //配置表名
public class UserDto {
    @Id //设置主键
    @KeySql(useGeneratedKeys = true) //允许JDBC支持自动生成主键
    private Integer id;
    private String name;
    private Integer age;
}

创建持久层(数据库层)我们这里用的是 mybatis给我们提供的抽象类 ,里面自带curd操作(简称通用mapper)
MyMapper .java

package com.cs.demo.mapper;

import com.cs.demo.dto.UserDto;
import tk.mybatis.mapper.common.Mapper;

public interface MyMapper extends Mapper<UserDto> {
}

创建事务层
MyService .java

package com.cs.demo.service;

import com.cs.demo.dto.UserDto;
import com.cs.demo.mapper.MyMapper;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;

import java.util.List;

@Component //注入到spring 容器里
public class MyService {

    @Autowired //从spring容器实例化对象
    private MyMapper myMapper;

    public List<UserDto> findAll() {
        List<UserDto> userDtos = myMapper.selectAll();
        return userDtos;
    }
}

创建表示层:
MyController .java

package com.cs.demo.controller;
import com.cs.demo.dto.UserDto;
import com.cs.demo.service.MyService;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RestController;

import java.util.List;
@RestController
public class MyController {

    @Autowired
    private MyService myService;

    @GetMapping("findAll")
    public List<UserDto> findAll(){
        List<UserDto> all = myService.findAll();
        return all;
    }
}

创建启动器:

package com.cs;
import tk.mybatis.spring.annotation.MapperScan;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
@SpringBootApplication
@MapperScan("com.cs.demo.mapper") //扫描我们的只定义mapper
public class SpringBootMybatis {
    public static void main(String[] args) {
        SpringApplication.run(SpringBootMybatis.class,args);
    }
}

执行结果:
在这里插入图片描述可以看到我们 的操作成功了.

那么他的原理是怎样的呢,让我们看一下之前对mybatis操作的图
在这里插入图片描述在这里插入图片描述我们通过工厂模式 创造出sqlSession,然后通过sqlSession动态代理 代理出我们的我们的连接对象,即我们查询数据库的方法,动态解析xml文件,动态拼装我们的sql语句,然后再通过jdbc协议发送sql语句到mysql中,这里为了防止sql注入问题,mybatis发送了两遍的sql,第一次:发送整体语句,例如 select * from user where id = ? .第二次:在1吧id的值发送给sql,最后mysql返回给我们后端结果.

其mybatis整合spring也是一样的他只不过是提前把之前我们很难搞的sql逆向工程统一搞了个工具类,然后我们只需要调用其工具类即可.

缓存

在之前我们要设置缓存需要这么设置

  1. 一级缓存: 基于 PerpetualCache 的 HashMap 本地缓存,其存储作用域为 Session,当 Session flush 或 close 之后,该 Session 中的所有 Cache 就将清空。
  2. 二级缓存与一级缓存其机制相同,默认也是采用 PerpetualCache,HashMap 存储,不同在于其存储作用域为 Mapper(Namespace),并且可自定义存储源,如 Ehcache。作用域为 namespance 是指对该 namespance 对应的 配置文件中所有的 select 操作结果都缓存,这样不同线程之间就可以共用二级缓存。启动二级缓存:在 mapper 配置 文件中:。
    二级缓存可以设置返回的缓存对象策略:。当 readOnly="true"时,表示二级缓存返
    回给所有调用者同一个缓存对象实例,调用者可以 update 获取的缓存实例,但是这样可能会造成其他调用者出现数
    据不一致的情况(因为所有调用者调用的是同一个实例)。当 readOnly="false"时,返回给调用者的是二级缓存总缓
    存对象的拷贝,即不同调用者获取的是缓存对象不同的实例,这样调用者对各自的缓存对象的修改不会影响到其他的
    调用者,即是安全的,所以默认是 readOnly=“false”;

其原理图(自己画的)
在这里插入图片描述

  • 一级缓存是基于SQLSession的缓存,一级缓存的内容不能跨SQLSession。由mybatis自动维护。不同的sqlsession之间的缓存区域是互相不影响的。
  • 二级缓存是基于映射文件的缓存(namespace),缓存范围比一级缓存更大,不同的SQLSession可以访问二级缓存的内容。哪些数据放入二级缓存需要自己指定。(常用,不经常修改,例如:类别,部门)
  • 在这里插入图片描述首先要手动开启mybatis二级缓存。

在config.xml设置二级缓存开关 , 还要在具体的mapper.xml开启二级缓存
1.

<settings>
    <!--开启二级缓存-->
    <setting name="cacheEnabled" value="true"/>       
</settings>

2.需要将映射的javapojo类实现序列化 (这个是我们之前通过逆向工程生成的辅助类)

      class User implements Serializable{}

3.

cache属性的简介:

eviction:代表的是缓存回收策略,目前MyBatis提供以下策略。

(1) LRU(Least Recently Used),最近最少使用的,最长时间不用的对象

(2) FIFO(First In First Out),先进先出,按对象进入缓存的顺序来移除他们

(3) SOFT,软引用,移除基于垃圾回收器状态和软引用规则的对象

(4) WEAK,弱引用,更积极的移除基于垃圾收集器状态和弱引用规则的对象。这里采用的是LRU,
移除最长时间不用的对形象

flushInterval:刷新间隔时间,单位为毫秒,这里配置的是100秒刷新,如果你不配置它,那么当
SQL被执行的时候才会去刷新缓存。

size:引用数目,一个正整数,代表缓存最多可以存储多少个对象,不宜设置过大。设置过大会导致内存溢出。
这里配置的是1024个对象

readOnly:只读,意味着缓存数据只能读取而不能修改,这样设置的好处是我们可以快速读取缓存,缺点是我们没有
办法修改缓存,他的默认值是false,不允许我们修改

操作过程:

sqlsession1查询用户id为1的信息,查询到之后,会将查询数据存储到二级缓存中。

如果sqlsession3去执行相同mapper下sql,执行commit提交,会清空该mapper下的二级缓存区域的数据

sqlsession2查询用户id为1的信息, 去缓存找 是否存在缓存,如果存在直接从缓存中取数据

禁用二级缓存:

在statement中可以设置useCache=false,禁用当前select语句的二级缓存,默认情况为true

在实际开发中,针对每次查询都需要最新的数据sql,要设置为useCache=“false” ,禁用二级缓存
flushCache标签:刷新缓存(清空缓存)

一般下执行完commit操作都需要刷新缓存,flushCache="true 表示刷新缓存,可以避免脏读
二级缓存应用场景

对于访问多的查询请求并且用户对查询结果实时性要求不高的情况下,可采用mybatis二级缓存,降低数据库访问量,提高访问速度,如电话账单查询

根据需求设置相应的flushInterval:刷新间隔时间,比如三十分钟,24小时等。。。
二级缓存局限性:

mybatis二级缓存对细粒度的数据级别的缓存实现不好,比如如下需求:对商品信息进行缓存,由于商品信息查询访问量大,但是要求用户每次都能查询最新的商品信息,此时如果使用mybatis的二级缓存就无法实现当一个商品变化时只刷新该商品的缓存信息而不刷新其它商品的信息,因为mybaits的二级缓存区域以mapper为单位划分,当一个商品信息变化会将所有商品信息的缓存数据全部清空。解决此类问题需要在业务层根据需求对数据有针对性缓存。

那么在我们的mybatis整合SpringBoot如何设置二级缓存

Mybatis 配置

  • #使全局的映射器启用或禁用缓存。
    mybatis.configuration.cache-enabled=true
  • #全局启用或禁用延迟加载。当禁用时,所有关联对象都会即时加载。
    mybatis.configuration.lazy-loading-enabled=true
  • #当启用时,有延迟加载属性的对象在被调用时将会完全加载任意属性。否则,每种属性将会按需要加载。
    mybatis.configuration.aggressive-lazy-loading=true
  • #是否允许单条sql 返回多个数据集 (取决于驱动的兼容性) default:true
    mybatis.configuration.multiple-result-sets-enabled=true
  • #是否可以使用列的别名 (取决于驱动的兼容性) default:true
    mybatis.configuration.use-column-label=true
  • #允许JDBC 生成主键。需要驱动器支持。如果设为了true,这个设置将强制使用被生成的主键,有一些驱动器不兼容不过仍然可以执行。 default:false
    mybatis.configuration.use-generated-keys=true
  • #指定 MyBatis 如何自动映射 数据基表的列 NONE:不隐射\u3000PARTIAL:部分 FULL:全部
    mybatis.configuration.auto-mapping-behavior=partial
  • #这是默认的执行类型 (SIMPLE: 简单; REUSE: 执行器可能重复使用prepared statements语句;BATCH: 执行器可以重复执行语句和批量更新)
    mybatis.configuration.default-executor-type=simple
  • #使用驼峰命名法转换字段。
    mybatis.configuration.map-underscore-to-camel-case=true
  • #设置本地缓存范围 session:就会有数据的共享 statement:语句范围 (这样就不会有数据的共享 ) defalut:session
    mybatis.configuration.local-cache-scope=session
  • #设置但JDBC类型为空时,某些驱动程序 要指定值,default:OTHER,插入空值时不需要指定类型
    mybatis.configuration.jdbc-type-for-null=null
  • #如果数据为空的字段,则该字段省略不显示,可以通过添加配置文件,规定查询数据为空是则返回null。
    mybatis.configuration.call-setters-on-nulls=true

那么我们只需要加上这么一段即可

mybatis:
  type-aliases-package: com.cs.dto.UserDto  #对应的实体类
  configuration:
    map-underscore-to-camel-case: true
    cache-enabled: true #开启二级缓存
  mapper-locations: mappers/*.xml #如果还想用之前的mapper.xml写sql语句也可以放在这里
发布了69 篇原创文章 · 获赞 6 · 访问量 2499

猜你喜欢

转载自blog.csdn.net/qq_40539437/article/details/104012551
今日推荐