Mybatis框架

Mybatis

1.Mybatis介绍

官网地址: https://mybatis.org/mybatis-3/zh/index.html

MyBatis 是一款优秀的持久层框架,它支持自定义 SQL、存储过程以及高级映射。
MyBatis 免除了几乎所有的 JDBC 代码以及设置参数和获取结果集的工作。
MyBatis 可以通过简单的 XML 或注解来配置和映射原始类型、接口和 Java POJO(Plain Old Java Objects,普通老式 Java 对象)为数据库中的记录。
MyBatis 本是apache的一个开源项目iBatis.

2.特点

  • 简单易学:本身就很小且简单。没有任何第三方依赖,最简单安装只要两个jar文件+配置几个sql映射文件易于学习,易于使用,通过文档和源代码,可以比较完全的掌握它的设计思路和实现。
  • 灵活:mybatis不会对应用程序或者数据库的现有设计强加任何影响。
  • sql写在xml里,便于统一管理和优化。通过sql语句可以满足操作数据库的所有需求。
  • 解除sql与程序代码的耦合:通过提供DAO层,将业务逻辑和数据访问逻辑分离,使系统的设计更清晰,更易维护,更易单元测试。sql和代码的分离,提高了可维护性。
  • 提供映射标签,支持对象与数据库的orm字段关系映射 提供对象关系映射标签,支持对象关系组建维护 提供xml标签,支持编写动态sql。

3.Mybatis入门案例

1.准备数据库

2.导入jar包


<dependency>
    <groupId>org.mybatis.spring.bootgroupId>
    <artifactId>mybatis-spring-boot-starterartifactId>
    <version>2.2.0version>
dependency>


<dependency>
    <groupId>mysqlgroupId>
    <artifactId>mysql-connector-javaartifactId>
dependency>

<dependency>
    <groupId>org.projectlombokgroupId>
    <artifactId>lombokartifactId>
dependency>

3.数据映射

持久层:POJO对象 数据库表
1.数据表:用户的数据信息,持久化到本地磁盘
2.POJO:程序通过对象封装数据信息
映射关系: 一个POJO对象要求映射一张数据表
1.对象名称 映射数据表表名
2.对象的属性 映射数据表中的字段
Mybatis方法定义四类:
List findall(); 返回多个值
User findAll2(); 返回一个值
int update(): 影响的行数
void update2(); 无返回值

编辑POJO对象:
Mybatis框架_第1张图片

4.编辑mybatis-config.xml配置文件


DOCTYPE configuration
        PUBLIC "-//mybatis.org//DTD Config 3.0//EN"
        "http://mybatis.org/dtd/mybatis-3-config.dtd">

<configuration>

    
    <environments default="development">

        
        <environment id="development">
            
            <transactionManager type="JDBC"/>
            
            <dataSource type="POOLED">
                <property name="driver" value="com.mysql.cj.jdbc.Driver"/>
                <property name="url" value="jdbc:mysql://127.0.0.1:3306/jt?serverTimezone=GMT%2B8&useUnicode=true&characterEncoding=utf8&autoReconnect=true&allowMultiQueries=true"/>
                
                <property name="username" value="root"/>
                
                <property name="password" value="root"/>
            dataSource>
        environment>
    environments>

    
    <mappers>
        <mapper resource="mybatis/mappers/UserMapper.xml"/>
    mappers>
configuration>

5.编辑UserMapper接口

public interface UserMapper {
    //指定接口方法    查询demo_user所有数据
    List<User> findAll();
}

6.编辑UserMapper.xml的映射文件

说明:由于mybatis需要操作数据库,编辑Sql语句,采用xml映射文件维护Sql语句
**关系
1.一个接口对应一个xml的映射文件
2.一个接口方法对应一个映射文件的Sql
namespace与接口对应,id表示接口方法,resultType返回值POJO对象的类型


DOCTYPE mapper
        PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN"
        "http://mybatis.org/dtd/mybatis-3-mapper.dtd">


<mapper namespace="com.jt.mapper.UserMapper">
    
    <select id="findAll" resultType="com.jt.pojo.User">
        select * from demo_user
    select>



mapper>

7.Mabatis加载mapper映射文件

Mybatis框架_第2张图片

3.Mybatis入门案例2

1.编辑TestMybatis

每个基于 MyBatis 的应用都是以一个 SqlSessionFactory 的实例为核心的。SqlSessionFactory 的实例可以通过 SqlSessionFactoryBuilder 获得。而 SqlSessionFactoryBuilder 则可以从 XML 配置文件或一个预先配置的 Configuration 实例来构建出 SqlSessionFactory 实例

public class TestMybatis {
    /**
     * 规则说明:
     *      1.创建SqlSessionFactory   工厂模式
     * */
    public void demo1() throws IOException {
        //1.1指定配置文件的根目录
        String resource = "mybatis-config.xml";
        //1.2通过I/O流 加载配置文件  org.apache.ibatis.io.Resources包路径
        InputStream inputStream = Resources.getResourceAsStream(resource);
        //1.3实例化工厂对象
        SqlSessionFactory sqlSessionFactory = new SqlSessionFactoryBuilder().build(inputStream);

    }
}

2.从SqlSessionFactory中获取SqlSession 数据库链接 + 传输器对象

既然有了 SqlSessionFactory,顾名思义,我们可以从中获得 SqlSession 的实例。SqlSession 提供了在数据库执行 SQL 命令所需的所有方法。你可以通过 SqlSession 实例来直接执行已映射的 SQL 语句。

//2.1获取SqlSession  通过SqlSession可以直接操作数据库
SqlSession sqlSession = sqlSessionFactory.openSession();
//2.2获取接口对象
UserMapper usermapper = sqlSession.getMapper(UserMapper.class);

3.执行业务调用

package com.jt;

import com.jt.mapper.UserMapper;
import com.jt.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.IOException;
import java.io.InputStream;
import java.util.List;

public class TestMybatis {
    /**
     * 规则说明:
     *      1.创建SqlSessionFactory   工厂模式
     *      2.获取SqlSession  数据库链接 + 传输器对象
     *      3.获取Mapper接口对象
     *      4.完成业务调用
     *      5.关闭链接
     * */
    @Test
    public void demo1() throws IOException {
        //1.1指定配置文件的根目录
        String resource = "mybatis-config.xml";
        //1.2通过I/O流 加载配置文件  org.apache.ibatis.io.Resources包路径
        InputStream inputStream = Resources.getResourceAsStream(resource);
        //1.3实例化工厂对象
        SqlSessionFactory sqlSessionFactory = new SqlSessionFactoryBuilder().build(inputStream);

        //2获取SqlSession  通过SqlSession可以直接操作数据库
        SqlSession sqlSession = sqlSessionFactory.openSession();
        //3获取接口对象
        UserMapper usermapper = sqlSession.getMapper(UserMapper.class);
        //4.调用接口方法
        List<User> userList = usermapper.findAll();
        System.out.println(userList);
        //5.暂时手动关闭链接
        sqlSession.close();
    }
}

4.Mybatis常见错误

1.jar包添加错误

2.配置文件名称不一致

在这里插入图片描述

3.数据源配置异常

数据库版本要求:MySQL5.5以上版本 mariaDB10 以上
驱动异常:Mybatis框架_第3张图片

4.映射文件加载错误

Mybatis框架_第4张图片

5.接口与映射文件不匹配

4.Mybatis配置

1.添加jar包,复制src文件夹

2.修改yml配置文件application.yml

3.关于主启动类异常说明

Mybatis框架_第5张图片
Mybatis框架_第6张图片

开箱即用规则
报错原理:由于Mybatis依赖了JDBC的jar包.,但是该jar包文件是启动项.,当主启动类运行时,开始加载主启动项。 但是JDBC需要链接数据库,所以必须有相关的配置信息.但是此时YML文件中没有数据源的配置,所以报错。

4.配置yml文件

yml 文件 0 不解析 如果字母以0开题则引号包裹
配置application.yml文件:配置端口号、配置数据源、配置映射文件

#1.配置端口号  注意空格
server:
  port: 8090
  servlet:
    context-path: /
#2.配置数据源
spring:
  datasource:
    driver-class-name: com.mysql.cj.jdbc.Driver
    url: jdbc:mysql://127.0.0.1:3306/jt?serverTimezone=GMT%2B8&useUnicode=true&characterEncoding=utf8&autoReconnect=true&allowMultiQueries=true
    username: root
    password: 123456
#3.配置映射文件
mybatis:
  type-aliases-package: com.jt.pojo
  #将所有的映射文件全部加载
  mapper-locations: classpath:/mappers/*.xml
  #开启驼峰映射
  configuration:
    map-underscore-to-camel-case: true

5.Mapper/Dao 持久层用 @Mapper注解

将Mapper接口交给Spring容器管理

package com.jt.mapper;

import com.jt.pojo.User;
import org.apache.ibatis.annotations.Mapper;

import java.util.List;
@Mapper     //将接口交给Spring容器管理Map
public interface UserMapper {
    //指定接口方法    查询demo_user所有数据
    List<User> findAll();
}

6.编辑测试类

package com.jt;

import com.jt.mapper.UserMapper;
import com.jt.pojo.User;
import org.junit.jupiter.api.Test;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.test.context.SpringBootTest;

import java.util.List;

@SpringBootTest
class MybatisDemo1ApplicationTests {

    @Autowired
    private UserMapper userMapper;
    @Test
    public void testDemo1(){
        List<User> userList = userMapper.findAll();
        System.out.println(userList);
    }
}

5.Mybatis基本用法

1.常见CURD操作,根据id查询

1.编辑接口类

package com.jt.mapper;

import com.jt.pojo.User;
import org.apache.ibatis.annotations.Mapper;

import java.util.List;
@Mapper
public interface UserMapper {
    List<User> findAll();
    //根据id查询数据库
    User findUserById(int id);
}

2.编辑测试类

@Test
public void testFindUserById(){
    int id = 1;
    userMapper.findUserById(id);
}

3.编辑映射文件UserMapper.xml

resultType 返回值的类型,封装为对象


<select id="findUserById" resultType="com.jt.pojo.User">
    select * from demo_user where id = #{id}
select>

2.SQL语句打印

编辑yml文件

#4.打印sql com.jt.mapper 下的sql日志
logging:
  level: 
    com.jt.mapper:debug

3.常见CURD操作,根据name、age查询

1.编辑接口类

package com.jt.mapper;

import com.jt.pojo.User;
import org.apache.ibatis.annotations.Mapper;

import java.util.List;
@Mapper     //将接口交给Spring容器管理Map
public interface UserMapper {
    //指定接口方法    查询demo_user所有数据
    List<User> findAll();
    //根据id查询数据库
    User findUserById(int id);

    List<User> findUserByNA(User user);
}

2.编辑测试类

/**
 * 知识点:
 *      1.如果是多个参数传递,则一般采用对象的方式封装
 * */
@Test
public void testFindByNa(){
    String name = "孙尚香";
    List<User> userList = userMapper.findUserByNA();
    System.out.println(userList);
}

3.编辑映射文件UserMapper.xml

    
    <select id="findUserByNA" resultType="com.jt.pojo.User">
        select * from demo_user where name = #{name} and age = #{age}
    select>
mapper>

4.查询age>18 age<100的用户

如果多个参数不方便使用User对象封装时,应该使用万能的集合Map
如果传递的参数是Map,则使用#{key}
xml转义字符:
1. > >
2. < <
3. & &
万能转义:

1.编辑UserMapper文件

<select id="findUserByAge" resultType="User">
    select * from demo_user where age > #{minAge} and age > #{maxAge}
select>

2.编辑测试类

/**
 * 知识点:
 *      如果多个参数不方便使用User对象封装时,应该使用万能的集合Map
 *
 * */
@Test
public void testFindUserByAge(){
    int minAge = 18;
    int maxAge = 100;
    Map<String,Integer> map = new HashMap();
    map.put("minAge", minAge);
    map.put("maxAge", maxAge);
    List<User> userList = userMapper.findUserByAge(map);
    System.out.println(userList);
}

3.编辑接口类

package com.jt.mapper;

import com.jt.pojo.User;
import org.apache.ibatis.annotations.Mapper;

import java.util.List;
import java.util.Map;

@Mapper     //将接口交给Spring容器管理Map
public interface UserMapper {
    //指定接口方法    查询demo_user所有数据
    List<User> findAll();
    //根据id查询数据库
    User findUserById(int id);

    List<User> findUserByNA(User user);

    List<User> findUserByAge(Map<String, Integer> map);
}

5.利用注解@Param将Map封装

mybatis只支持单值传参 将多值封装为单值
@Param将数据封装为Map集合
@Param(“key”) int minAge(值)

1.编辑测试类

/**
 * 知识点:
 *      利用注解实现数据的封装,封装Map集合
 * */
@Test
public void testFindUserByAge2(){
    int minAge = 18;
    int maxAge = 100;
    List<User> userList = userMapper.findUserByAge2(minAge,maxAge);
    System.out.println(userList);
}

2.编辑接口类

//mybatis只支持单值传参    将多值封装为单值
    //注解:@Param
    List<User> findUserByAge2(@Param("minAge") int minAge, @Param("maxAge") int maxAge);

3.编辑映射文件

<select id="findUserByAge2" resultType="User">
     #{minAge} and age < #{maxAge}

    ]]>
select>

6.模糊查询

1.业务需求

查询name字段中包含“君”的用户

2.编辑测试方法

@Test
public void testFindUserByLike(){
	//String name = "%"+"君"+"%";
    String name = "君";
    List<User> userList = userMapper.findUserByLike(name);
    System.out.println(userList);
}

3.编辑接口类

List<User> findUserByLike(String name);

4.编辑映射文件

<!--windows系统:数据库不区分大小写
    linux系统: 区分大小写
-->
<select id="findUserByLike" resultType="User">
    select * from demo_user where name like "%"#{name}"%"
</select>

5.like与concat一起用防止sql注入

Mybatis框架_第7张图片

7.Sql标签用法

1.业务需求

说明:Sql语句中经常出现重复的数据,如果每次重复的内容都自己手写,开发效率低
用法:Sql标签
优化:将公共的Sql进行抽取
优势:Sql标签可以

2.Sql标签


<sql id="tableColumn">
    id,name,age,sex
sql>
    <select id="findUserByLike" resultType="User">
        select <include refid="tableColumn"/> from demo_user where name like "%"#{name}"%"
    select>

8.Mybatis中的集合参数写法

1.业务需求

查询id=1,2,3,5,7的数据

2.编辑测试方法

@Test
public void testFindListByIn(){
    int[] array = {1,2,3,5,7};
    List<User> userList = userMapper.findListByIn(array);
    System.out.println(userList);
}

3.编辑接口类

List<User> findListByIn(int[] array);

4.编辑映射文件

关于Mybatis的遍历的写法:
foreach标签:
1.collection 需要遍历的集合
1.1数组 关键字:array
1.2list集合 关键字:list
1.3Map 关键字:key
2.open/close 循环体的开始和结束 可以写到循环之外简化标签
3.item 当前遍历数据的变量 是id
4.separator 分割符

<select id="findListByIn" resultType="User">
    select * from demo_user where id in(
    <foreach collection="array" item="id" separator=",">
        #{id}
    foreach>
    )
select>

6.动态Sql

1.动态Sql-where条件

需求:
根据对象中不为null的数据,充当where条件,进行查询
编辑测试方法:

@Test
public void testDemo1(){
    User user = new User();
    user.setAge(18).setSex("女");    //动态变化的数据
    List<User> userList = userMapper2.findUserList(user);
    System.out.println(userList);
}

编辑接口类:

List<User> findUserList(User user);

编辑映射文件:
根据对象中不为空的属性当作where条件
语法:
1.如果判断成立则动态拼接属性 id = #{id}
2.where标签 去除where后边多余的and/or


<select id="findUserList" resultType="User">
    select * from demo_user
    <where>
        <if test="id != null">id=#{id}if>
        <if test="name != null">and name=#{name}if>
        <if test="age != null"> and age=#{age}if>
        <if test="sex != null"> and sex=#{sex}if>
    where>
select>

2.动态Sql-set条件

编辑测试方法:

//执行动态的更新操作
//根据对中不为null的元素,充当set条件
@Test
public void testDemo2(){
    User user = new User();
    user.setId(235).setName("王二麻子").setAge(25).setSex("男");
    userMapper2.updateUser(user);
    System.out.println("更新成功");
}

编辑接口类:

void updateUser(User user);

编辑映射文件:

<update id="updateUser">
    update demo_user
    <set>
        <if test="name != null">name = #{name},if>
        <if test="age != null">age = #{age},if>
        <if test="sex != null">sex = #{sex}if>
    set>
    where id = #{id}
update>

3.动态Sql-choose、when、otherwise

如果不想使用所有的条件可以使用choose类似于java中的switch
语法:如果name有值,则按照name查询,否则按照age查询,age无值则按照 sex查询数据
编辑测试方法:

@Test
public void testDemo3(){
    User user = new User();
    user.setName(null).setAge(18).setSex("女");
    List<User> userList = userMapper2.findUserByNS(user);
    System.out.println(userList);
}

编辑接口类:

List<User> findUserByNS(User user);

编辑映射文件:

<select id="findUserByNS" resultType="User">
    select * from demo_user
    <where>
        <choose>
            <when test="name != null">name =#{name}when>
            <when test="age != null">age =#{age}when>
            <otherwise>sex = #{sex}otherwise>
        choose>
    where>
select>

7.resultMap

说明:当表中字段与pojo中的属性名称不一致时或者进行多表联查时,需要使用resultMap的方式进行映射
表中字段名称与对象中属性名称不一致,结果数据不能映射

1.建表:

Mybatis框架_第8张图片

2.创建pojo Dog类:

@Data
@Accessors(chain = true)
@NoArgsConstructor
@AllArgsConstructor
public class Dog {
    private Integer dogId;
    private String dogName;
    private Integer age;
}

3.关于返回属性的说明

  1. resultType:只能支持字段的名称属性的名称一致时,才能自动映射
  2. resultMap:可以支持任意类型的映射,万能的结构

8.开启驼峰规则映射

说明:在业务中经常出现该现象: 字段user_id 属性userId 属性和字段有驼峰映射规则,但是不采用resultType方式映射,则不能正常赋值。
解决方案:
1.resultMap 繁琐
2开启驼峰映射规则

9.Mybatis关联关系

1.常见关联关系

1.一对一 一个员工对应一个部门
2.一个多 老师对应多个学生/一个部门对应多个员工
3.多对多 一个老师对应多个学生 一个学生对应多个老师(双向的多对多)

2.创建数据表

emp表
Mybatis框架_第9张图片
dept表
在这里插入图片描述

3.关联查询

1.笛卡尔积

特点:只获取两张表的交集

SELECT * FROM emp,dept WHERE emp.dept_id=dept.dept_id

2.连接查询

分类:1左连接(查询左表所有数据) 2内连接 3右连接(查询右表所有数据)

#左连接
SELECT * FROM emp LEFT JOIN dept ON emp.dept_id=dept.dept_id

4.一对一封装

员工对部门
1.如果操作单表 一般使用resultType
2.如果进行关联操作 一般使用resultMap
3.如果是多表关联操作,不允许出现重复字段名

**关于自动映射规则:**
1.没有映射关联时如果属性和字段名相同,则可以省略不写
2.有关联映射,则需要添加自动映射开关autoMapping="true",自动开关只对当前对象有效

1.编辑Emp实例类

@Data
@Accessors(chain = true)
@NoArgsConstructor
@AllArgsConstructor
public class Emp implements Serializable {
    private Integer id;
    private String name;
    private Integer age;
    //关联关系:一个员工对应一个部门
    private Dept dept;
    //private Integer deptId;
}

2.编辑测试方法

@Test
public void testOneToOne(){
    List<Emp> empList = empMapper.findAll();
    System.out.println(empList);
}

3.编辑映射文件

关联另外的表用标签,


DOCTYPE mapper
        PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN"
        "http://mybatis.org/dtd/mybatis-3-mapper.dtd">


<mapper namespace="com.jt.mapper.EmpMapper">
    
    <select id="findAll" resultMap="empRM">
        select <include refid="tableColumn"/> from emp,dept where emp.dept_id=dept.dept_id
    select>
    
    <resultMap id="empRM" type="Emp" autoMapping="true">
        
        <id column="id" property="id"/>
        
        <association property="dept" javaType="Dept" autoMapping="true">
            
            <id column="dept_id" property="deptId">id>
            
            
        association>
    resultMap>
    <sql id="tableColumn">
        emp.id,emp.name,emp.age,dept.dept_id,dept.dept_name
    sql>
mapper>

5.一对多封装

部门对员工

1.编辑测试方法

//一对多,一个部门中要求获取多个员工
@Test
public void testOneToMore(){
    List<Dept> deptList = deptMapper.findAll();
    System.out.println(deptList);
}

2.编辑实例类

@Data
@Accessors(chain = true)
@NoArgsConstructor
@AllArgsConstructor
public class Dept implements Serializable {
    private Integer deptId;
    private String deptName;
    //关联关系:一个部门对应多个员工
    private List<Emp> emps;
}

3.编辑映射文件

一对多关联另外表时用标签,


DOCTYPE mapper
        PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN"
        "http://mybatis.org/dtd/mybatis-3-mapper.dtd">


<mapper namespace="com.jt.mapper.DeptMapper">

    <select id="findAll" resultMap="deptRM">
        select dept.dept_name,emp.*
         from dept,emp
         where dept.dept_id = emp.dept_id
    select>
    <resultMap id="deptRM" type="Dept" autoMapping="true">
        
        <id column="dept_id" property="deptId"/>
        
            <collection property="emps" ofType="Emp" autoMapping="true">
                <id column="id" property="id"/>
            collection>
    resultMap>
mapper>

10.Mabatis注解开发

1.编辑测试类

package com.jt;

import com.jt.mapper.DeptMapper;
import com.jt.mapper.EmpMapper;
import com.jt.mapper.UserAnnoMapper;
import com.jt.mapper.UserMapper;
import com.jt.pojo.Dept;
import com.jt.pojo.Emp;
import com.jt.pojo.User;
import org.apache.ibatis.annotations.Select;
import org.junit.jupiter.api.Test;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.test.context.SpringBootTest;
import org.springframework.transaction.annotation.Transactional;

import java.util.List;

@SpringBootTest
class MybatisDemo1ApplicationTests4 {

    @Autowired
    private UserAnnoMapper annoMapper;

    @Test
    //利用注解可以根据返回值类型,自动映射
    public void testFindAll(){
        List<User> list = annoMapper.findAll();
        System.out.println(list);
    }
    @Test
    //利用注解可以根据返回值类型,自动映射
    public void testFindAll2(){
        int id = 1;
        List<User> list = annoMapper.findUserById(id);
        System.out.println(list);
    }
    //根据姓名查询
    @Test
    public void testFindByNa(){
        User user = new User();
        user.setName("王六子");
        List<User> list = annoMapper.findUserByNa(user);
        System.out.println(list);
    }
    //插入数据
    @Test
    public void testInsert(){
        User user = new User();
        user.setName("刘阳").setAge(22).setSex("女");
        int rows = annoMapper.insertUser(user);
        System.out.println(rows);
    }
    //修改数据
    @Test
    public void testSetUser(){
        User user = new User();
        user.setId(236).setName("刘阳").setAge(21).setSex("女");
        int rows = annoMapper.updateUser(user);
        System.out.println(rows);
    }
    //删除数据
    @Test
    public void testDelete(){
        User user = new User();
        user.setId(236);
        int rows = annoMapper.deleteUser(user);
        System.out.println(rows);
    }
}

2.编辑接口类

package com.jt.mapper;

import com.jt.pojo.User;
import org.apache.ibatis.annotations.*;

import java.util.List;

//该Mapper主要测试注解开发
@Mapper
@CacheNamespace     //使用注解的二级缓存
public interface UserAnnoMapper {
    @Select("select * from demo_user")
    List<User> findAll();
    @Select("select * from demo_user where id = #{id}")
    List<User> findUserById(int id);
    @Insert("insert into demo_user values(null,#{name},#{age},#{sex})")
    int insertUser(User user);
    @Update("update demo_user set id= #{id},age = #{age},sex = #{sex} where name = #{name}")
    int updateUser(User user);
    @Delete("delete from demo_user where id = #{id}")
    int deleteUser(User user);
    @Select("select * from demo_user where name = #{name}")
    List<User> findUserByNa(User user);

    List<User> findCache1();
}

11.Mybstis缓存

1.缓存说明

说明: 如果相同的数据需要多次查询,则可以使用缓存的方式处理,提高用户的响应速度。
mybatis中提供了两种缓存机制:
一级缓存: SqlSession级别 在同一个sqlSession内实现数据共享 默认开启
二级缓存:SqlSessionFactory级别 由同一个sqlSessionFactory生产的SqlSession数据共享 默认开启 + 配置
易错项:二级缓存默认开启

3.缓存测试

说明:SpringBoot在使用一二级缓存时,有个别特殊要求注意

3.1一级缓存测试(@Transactional)

现象:采用SpringBoot的方式进行测试时,sql执行多次,一级缓存无效
解决:添加事务的注解,SpringBoot中添加了之后,默认采用一个SqlSession

编辑测试方法:

@Test
@Transactional  //添加事务
public void testCache1(){
    List<User> userList1 = userMapper.findCache1();
    List<User> userList2 = userMapper.findCache1();
    List<User> userList3 = userMapper.findCache1();
    List<User> userList4 = userMapper.findCache1();
}

3.2二级缓存测试

测试策略:
说明:为了构建多个mapper对象,需要准备多个线程进行测试,可以通过浏览器让用户发起多次请求之后,测试二级缓存是否有效。
层级代码结构:

  1. Controller 层 SpringMVC 面向接口编程 2:2:1
  2. Service 层 Spring
  3. Mapper/Dao层 Mybatis
    Mybatis框架_第10张图片编辑Mapper层
List<User> findCache1();

编辑service层:
编辑UserService接口类:

package com.jt.service;

import com.jt.pojo.User;

import java.util.List;

public interface UserService {
    List<User> findCache1();
    List<User> findAll();
}

编辑UserServiceImpl实现类:

package com.jt.service;

import com.jt.mapper.UserAnnoMapper;
import com.jt.pojo.User;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;

import java.util.List;
@Service
public class UserServiceImpl implements UserService {

    @Autowired
    private UserAnnoMapper userMapper;

    @Override
    public List<User> findCache1() {
        return userMapper.findCache1();
    }

    @Override
    public List<User> findAll() {
        return userMapper.findAll();
    }
}

编辑controller类:

package com.jt.controller;

import com.jt.pojo.User;
import com.jt.service.UserService;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.ResponseBody;
import org.springframework.web.bind.annotation.RestController;

import java.util.List;

@RestController
@ResponseBody
public class UserController {
    @Autowired
    private UserService userService;
    /**
     * 要求返回List集合的JSON串
     * */
    @GetMapping("/findCache")
    public List<User> findCache1(){

        return userService.findCache1();
    }
    @GetMapping("/findAll")
    public List<User> findAll(){

        return userService.findAll();
    }
}
3.2.1使用标签开启二级缓存

DOCTYPE mapper
        PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN"
        "http://mybatis.org/dtd/mybatis-3-mapper.dtd">


<mapper namespace="com.jt.mapper.UserAnnoMapper">
    
    <cache/>
    <select id="findCache1" resultType="User">
        select * from demo_user
    select>

mapper>
3.2.1使用二级注解开启二级缓存@CacheNamespace

业务说明: Mybatis中采用注解方式的查询和xml映射文件的查询的方式不一样. 两者不可以混用.
使用注解的二级缓存。
Mybatis框架_第11张图片

12.传入参数类型

parameterType为传入参数类型,resultType传出参数类型,resultMap当实体类属性名与数据库字段名不相同时使用

你可能感兴趣的:(mybatis,java)