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包

<!--mybatis依赖包-->
<dependency>
    <groupId>org.mybatis.spring.boot</groupId>
    <artifactId>mybatis-spring-boot-starter</artifactId>
    <version>2.2.0</version>
</dependency>

<!--jdbc依赖包-->
<dependency>
    <groupId>mysql</groupId>
    <artifactId>mysql-connector-java</artifactId>
</dependency>
<!--lombok依赖包-->
<dependency>
    <groupId>org.projectlombok</groupId>
    <artifactId>lombok</artifactId>
</dependency>

3.数据映射

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

编辑POJO对象:
在这里插入图片描述

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

<?xml version="1.0" encoding="UTF-8" ?>
<!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">
            <!--Mybatis采用jdbc的事务控制-->
            <transactionManager type="JDBC"/>
            <!--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&amp;useUnicode=true&amp;characterEncoding=utf8&amp;autoReconnect=true&amp;allowMultiQueries=true"/>
                <!--用户名-->
                <property name="username" value="root"/>
                <!--密码-->
                <property name="password" value="root"/>
            </dataSource>
        </environment>
    </environments>

    <!--Mybatis加载Mapper映射文件-->
    <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对象的类型

<?xml version="1.0" encoding="UTF-8" ?>
<!DOCTYPE mapper
        PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN"
        "http://mybatis.org/dtd/mybatis-3-mapper.dtd">

<!--1.namespace是mybaits映射文件的唯一标识,与接口对应-->
<mapper namespace="com.jt.mapper.UserMapper">
    <!--2.执行业务操作
         id 表示接口方法
          resultType 返回值的POJO对象类型User
    -->
    <select id="findAll" resultType="com.jt.pojo.User">
        select * from demo_user
    </select>
<!--    <insert></insert>-->
<!--    <update></update>-->
<!--    <delete></delete>-->
</mapper>

7.Mabatis加载mapper映射文件

在这里插入图片描述

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 以上
驱动异常:在这里插入图片描述

4.映射文件加载错误

在这里插入图片描述

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

4.Mybatis配置

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

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

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

在这里插入图片描述
在这里插入图片描述

开箱即用规则
报错原理:由于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<userMapper,JDK代理对象>
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 返回值的类型,封装为对象

<!--根据id查询数据库
    动态取值:#{key}
-->
<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<userMapper,JDK代理对象>
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
    <!--根据名称和age查询数据
         知识点:别名包  在配置文件中指定包路径:可以自动的实现包路径的拼接
         resultType规则:
            1.首先根据别名包匹配,设定。。
            2.如果匹配不成功,则按照路径匹配
         参数传递规则:
            1.如果是单个参数,则使用#{key}  获取的参数的值
            2.如果是对象参数,则使用#{属性} 获取的是属性值
    -->
    <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. > &gt;
2. < &lt;
3. & &amp;
万能转义:<![CDATA[xxx]]>

1.编辑UserMapper文件
<select id="findUserByAge" resultType="User">
    select * from demo_user where age > #{minAge} and age &gt; #{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<userMapper,JDK代理对象>
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">
    <![CDATA[

    select * from demo_user where age > #{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注入

在这里插入图片描述

7.Sql标签用法

1.业务需求

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

2.Sql标签
<!--Sql标签:抽取公共的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,array/list> 关键字: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

<!--根据对象中不为空的属性当作where条件
    语法:
        1.如果判断成立则东态拼接属性  <if test="id != null">#{id}</if>
        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.建表:

在这里插入图片描述

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表
在这里插入图片描述
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.编辑映射文件

关联另外的表用标签,

<?xml version="1.0" encoding="UTF-8" ?>
<!DOCTYPE mapper
        PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN"
        "http://mybatis.org/dtd/mybatis-3-mapper.dtd">

<!--1.namespace是mybatis映射文件的唯一标识,与接口对应-->
<mapper namespace="com.jt.mapper.EmpMapper">
    <!--
    规则:
        1.如果操作单表  一般使用resultType
        2.如果进行关联操作  一般使用resultMap
        3.如果是多表关联操作,不允许出现重复字段名
    -->
    <select id="findAll" resultMap="empRM">
        select <include refid="tableColumn"/> from emp,dept where emp.dept_id=dept.dept_id
    </select>
    <!--
        关于自动映射规则:
            1.没有映射关联时如果属性和字段名相同,则可以省略不写
            2.有关联映射,则需要添加自动映射开关autoMapping="true"
                            自动开关只对当前对象有效
    -->
    <resultMap id="empRM" type="Emp" autoMapping="true">
        <!--id代表主键-->
        <id column="id" property="id"/>
        <!--一对一关联封装
            知识点:
                1.一对一关联association标签
                2.必须要指定属性的类型  javaType属性
        -->
        <association property="dept" javaType="Dept" autoMapping="true">
            <!--主键必填-->
            <id column="dept_id" property="deptId"></id>
            <!--由于开启驼峰规则,下列可以省略-->
            <!--<result column="dept_name" property="deptName"/>-->
        </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.编辑映射文件

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

<?xml version="1.0" encoding="UTF-8" ?>
<!DOCTYPE mapper
        PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN"
        "http://mybatis.org/dtd/mybatis-3-mapper.dtd">

<!--1.namespace是mybatis映射文件的唯一标识,与接口对应-->
<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代表主键-->
        <id column="dept_id" property="deptId"/>
        <!--一对多封装 collection-->
            <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
    在这里插入图片描述编辑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使用标签开启二级缓存
<?xml version="1.0" encoding="UTF-8" ?>
<!DOCTYPE mapper
        PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN"
        "http://mybatis.org/dtd/mybatis-3-mapper.dtd">

<!--1.namespace是mybatis
s映射文件的唯一标识,与接口对应-->
<mapper namespace="com.jt.mapper.UserAnnoMapper">
    <!--
        1.让二级缓存在当前Mapper层有效
        2.POJO必须序列化
    -->
    <cache/>
    <select id="findCache1" resultType="User">
        select * from demo_user
    </select>

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

业务说明: Mybatis中采用注解方式的查询和xml映射文件的查询的方式不一样. 两者不可以混用.
使用注解的二级缓存。
在这里插入图片描述

12.传入参数类型

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

  • 1
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值