文章目录

1. Mybatis入门

1.0 JDBC代码

 //利用jdbc,完成新增的功能
    private static void method2() throws Exception{
        //1,注册驱动
        Class.forName("com.mysql.jdbc.Driver");
        //2,获取数据库的连接
        //数据传输协议   数据库的ip 端口号 数据库名
        String url = "jdbc:mysql://localhost:3306/cgb2107";
        Connection c = DriverManager.getConnection(url,"root","root");
        //3,获取传输器
        Statement s = c.createStatement();
        //4,利用传输器执行  增删改的SQL
        //executeUpdate()用来执行增删改的SQL,只返回影响行数
        int rows = s.executeUpdate(
                "INSERT INTO emp(ename,job) VALUES('rose','副总')");
        //5,释放资源
        //r.close();//结果集
        s.close();//传输器
        c.close();//连接
    }

从中可以看出JDBC的开发效率很低.

1.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, 2010年这个项目由apache software foundation 迁移到了google code,并且改名为MyBatis 。
  • 2013年11月迁移到Github。

1.2 Mybatis源码

mybatis源码

1.3 Mybatis特点

  • MyBatis 是支持定制化 SQL、存储过程以及高级映射的优秀的持久层框架
  • MyBatis 避免了几乎所有的 JDBC 代码和手动设置参数以及获取结果集
  • MyBatis可以使用简单的XML或注解用于配置和原始映射,将接口和Java的POJO(Plain Ordinary Java Object,普通的Java对象)映射成数据库中的记录
  • Mybatis 是一个 半自动的ORM(Object Relation Mapping)框架

1.4 Mybatis入门案例

1.4.1 导入jar包

<?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.atguigu</groupId>
    <artifactId>mybatis_demo1</artifactId>
    <version>1.0-SNAPSHOT</version>
    
    <properties>
        <maven.compiler.source>8</maven.compiler.source>
        <maven.compiler.target>8</maven.compiler.target>
    </properties>

    <dependencies>
        <!--导入MySQL的驱动包-->
        <dependency>
            <groupId>mysql</groupId>
            <artifactId>mysql-connector-java</artifactId>
            <version>8.0.16</version>
        </dependency>

        <!--导入MyBatis的jar包-->
        <dependency>
            <groupId>org.mybatis</groupId>
            <artifactId>mybatis</artifactId>
            <version>3.5.6</version>
        </dependency>

        <!--junit-->
        <dependency>
            <groupId>junit</groupId>
            <artifactId>junit</artifactId>
            <version>4.12</version>
            <scope>test</scope>
        </dependency>

        <!--log4j-->
        <dependency>
            <groupId>log4j</groupId>
            <artifactId>log4j</artifactId>
            <version>1.2.17</version>
        </dependency>

        <!--导入lombokjar包-->
        <dependency>
            <groupId>org.projectlombok</groupId>
            <artifactId>lombok</artifactId>
            <version>1.18.12</version>
            <scope>provided</scope>
        </dependency>
    </dependencies>
</project>

1.4.2 编辑User POJO对象

在这里插入图片描述

@Data
@Accessors(chain = true)
public class User implements Serializable {
    private Integer id;
    private String name;
    private Integer age;
    private String sex;
}

1.4.3 编辑mybaits-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">
            <transactionManager type="JDBC"/>
            <dataSource type="POOLED">
                <property name="driver" value="com.mysql.cj.jdbc.Driver"/>
                <property name="url" value="jdbc:mysql://localhost:3306/atweb?serverTimezone=UTC&amp;rewriteBatchedStatements=true&amp;characterEncoding=utf-8"/>
                <property name="username" value="root"/>
                <property name="password" value="root"/>
            </dataSource>
        </environment>
    </environments>
    <!--引入映射文件-->
    <mappers>
        <mapper resource="mappers/UserMapper.xml"/>
    </mappers>
</configuration>

1.4.4 编辑UserMapper接口

public interface UserMapper {

    List<User> getAllUser();

}

1.4.5 编辑接口实现类Mapper映射文件

<?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">
<mapper namespace="com.atguigu.mybatis.mapper.UserMapper">

    <select id="getAllUser" resultType="com.atguigu.mybatis.pojo.User">
        select * from demo_user
    </select>

</mapper>

1.4.6 mybatis关联映射文件

在这里插入图片描述

1.4.7 编辑SqlSessionFactory

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

	 	/*创建SqlSessionFactory*/
        String resource = "mybatis/mybatis-config.xml";
        InputStream inputStream = Resources.getResourceAsStream(resource);
        SqlSessionFactory sqlSessionFactory = new SqlSessionFactoryBuilder().build(inputStream);

1.4.8 从 SqlSessionFactory 中获取 SqlSession

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

	@Test
    public void testDemo1() throws IOException {
        /*创建SqlSessionFactory*/
        String resource = "mybatis/mybatis-config.xml";
        InputStream inputStream = Resources.getResourceAsStream(resource);
        SqlSessionFactory sqlSessionFactory = new SqlSessionFactoryBuilder().build(inputStream);

        /*从SqlSessionFactory中获取sqlSession*/
        SqlSession sqlSession = sqlSessionFactory.openSession();
    }

1.4.9 执行业务调用

 @Test
    public void testDemo1() throws IOException {

        /*创建SqlSessionFactory*/
        String resource = "mybatis/mybatis-config.xml";
        InputStream inputStream = Resources.getResourceAsStream(resource);
        SqlSessionFactory sqlSessionFactory = new SqlSessionFactoryBuilder().build(inputStream);

        /*从SqlSessionFactory中获取sqlSession*/
        SqlSession sqlSession = sqlSessionFactory.openSession();

        /*获取mapper接口,执行接口方法*/
        UserMapper userMapper = sqlSession.getMapper(UserMapper.class);
        List<User> userList = userMapper.findAll();
        System.out.println(userList);
    }

1.4.10 mybatis入门案例总结

Mysql入门实现步骤:
1.编辑mybatis-config.xml核心配置文件
1.1执行数据源配置
2.编辑POJO实体对象.要求与数据库表中的字段一一对应
3.编辑Mapper接口. 添加接口方法
4.编辑接口的实现类(配置文件方式) 要求namespace id resultType
5.mybatis加载指定的mapper映射文件
6.创建SqlSessionFactory工厂对象
7.获取SqlSession,开启数据库链接
8.获取接口对象(代理对象)
9.调用接口方法,获取返回值结果
10.关闭sqlSession链接.

1.5 Mybatis常见错误

1.5.1 BindingException异常说明

报错说明1:

org.apache.ibatis.binding.BindingException: Type interface com.jt.mapper.UserMapper is not known to the MapperRegistry.

解决方案1:
检查namespace命名是否与接口一致

报错说明2:

org.apache.ibatis.binding.BindingException: Invalid bound statement (not found): com.jt.mapper.UserMapper.findAll

解决方案2:
检查xml映射文件中的ID是否与接口方法一致.

报错说明3:

The error may exist in mybatis/mappers/UserMapper2.xml

解决方案3:
检查mybatis核心文件加载mapper映射文件的路径是否正确.

1.6 SqlSession 简化操作

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.jupiter.api.BeforeEach;
import org.junit.jupiter.api.Test;
import org.springframework.boot.test.context.SpringBootTest;

import java.io.IOException;
import java.io.InputStream;
import java.util.List;

class MybatisApplicationTests {

    private SqlSessionFactory sqlSessionFactory;

    @BeforeEach
    public void init() throws IOException {
        /*创建SqlSessionFactory*/
        String resource = "mybatis/mybatis-config.xml";
        InputStream inputStream = Resources.getResourceAsStream(resource);
        sqlSessionFactory = new SqlSessionFactoryBuilder().build(inputStream);
    }
    
    @Test
    public void testDemo2() {
        SqlSession sqlSession = sqlSessionFactory.openSession();
        UserMapper userMapper = sqlSession.getMapper(UserMapper.class);
        List<User> userList = userMapper.findAll();
        System.out.println(userList);
        sqlSession.close();
    }
}

1.7 SqlSession扩展方法(过时不建议使用)

说明: 可以通过namespace名称.ID的方式直接调用sql

在这里插入图片描述

 //知识扩展,利用namespace获取数据
    @Test
    public void testDemo3() {
        SqlSession sqlSession = sqlSessionFactory.openSession();
        List<User> userList = sqlSession.selectList("com.jt.mapper.UserMapper.findAll");
        System.out.println(userList);
        sqlSession.close();
    }

1.8 日志功能

1.8.1 引入日志文件目的

  • 设定级别,统一管理
    日志框架会按照事件的严重程度来划分级别,例如:

    • 错误(Error):表示程序运行出错,比如抛异常等情况。
    • 警告(Warning):表示程序运行过程中有潜在风险,但此时并没有报错。
    • 信息(Info):表示程序运行过程中完成了一个关键动作,需要以程序运行信息的形式告知开发者。
    • 调试(Debug):表示程序运行过程中更加细致的信息,协助程序员调试程序。
  • 灵活指定输出位置
    使用日志框架不一定是打印到控制台,也可以保存到文件中或者保存到数据库。这就看具体的项目维护需求。

  • 自定义日志格式
    打印日志数据可以使用日志框架的默认格式,也可以根据需要定制。
    在这里插入图片描述

  • 基于日志分析问题
    将来我们开发的应用系统中,不仅包含Java代码,还有很多中间件服务器。任何子系统出现故障我们都是通过日志来定位问题、分析故障原因。甚至更复杂的系统还会专门开发日志子系统,在主系统出现问题时抓取日志数据供维护人员参考。

1.8.2 常见日志

在这里插入图片描述

1.8.3 导入jar包

	<!-- 日志 , 会自动传递slf4j门面-->
   <dependency>
     <groupId>ch.qos.logback</groupId>
     <artifactId>logback-classic</artifactId>
     <version>1.2.3</version>
   </dependency>

1.8.4 日志入门案例

public class TestLog {
    private Logger logger = LoggerFactory.getLogger(TestLog.class);

    @Test
    public void testlog(){
        logger.debug("hello debug");
        logger.info("hello info");
        logger.warn("hello warning");
        logger.error("hello error");
    }
}

1.8.5 自定义日志

Logback要求配置文件名称必须是logback.xml,存放路径在main/resources目录下。
在这里插入图片描述

<?xml version="1.0" encoding="UTF-8"?>
<configuration debug="true">
    <!-- 指定日志输出的位置,ConsoleAppender表示输出到控制台 -->
    <appender name="STDOUT"
              class="ch.qos.logback.core.ConsoleAppender">
        <encoder>
            <!-- 日志输出的格式 -->
            <!-- 按照顺序分别是:时间、日志级别、线程名称、打印日志的类、日志主体内容、换行 -->
            <pattern>[%d{HH:mm:ss.SSS}] [%-5level] [%thread] [%logger] [%msg]%n</pattern>
            <charset>UTF-8</charset>
        </encoder>
    </appender>

    <!-- 设置全局日志级别。日志级别按顺序分别是:TRACE、DEBUG、INFO、WARN、ERROR -->
    <!-- 指定任何一个日志级别都只打印当前级别和后面级别的日志。 -->
    <root level="DEBUG">
        <!-- 指定打印日志的appender,这里通过“STDOUT”引用了前面配置的appender -->
        <appender-ref ref="STDOUT" />
    </root>

    <!-- 根据特殊需求指定局部日志级别,可也是包名或全类名。 -->
    <logger name="com.atguigu.mybatis" level="DEBUG" />

</configuration>

1.9 动态配置数据源

1.9.1 编辑properties文件

说明: 在src/main/resources/jdbc.properties 创建配置文件
在这里插入图片描述

jdbc.driver=com.mysql.cj.jdbc.Driver
jdbc.url=jdbc:mysql://localhost:3306/atweb?serverTimezone=UTC&rewriteBatchedStatements=true&characterEncoding=utf-8
jdbc.username=root
jdbc.password=root

1.9.2 动态获取数据源信息

<?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>

    <!--
        (properties?,settings?,typeAliases?,typeHandlers?,objectFactory?,objectWrapperFactory?,reflectorFactory?,plugins?,environments?,databaseIdProvider?,mappers?)".
    -->
    <properties resource="jdbc.properties"></properties>

    <!--设置连接数据库的环境-->
    <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://localhost:3306/atweb?serverTimezone=UTC&amp;rewriteBatchedStatements=true&amp;characterEncoding=utf-8"/>
                <property name="username" value="root"/>
                <property name="password" value="root"/>-->
                <property name="driver" value="${jdbc.driver}"/>
                <property name="url" value="${jdbc.url}"/>
                <property name="username" value="${jdbc.username}"/>
                <property name="password" value="${jdbc.password}"/>
            </dataSource>
        </environment>
    </environments>

    <!--引入映射文件-->
    <mappers>
        <mapper resource="mappers/UserMapper.xml"/>
    </mappers>
</configuration>

1.10 Mybatis属性定义

1.10.1 别名定义

可以通过别名配置简化返回值操作

1.配置文件别名 注意位置 在environments环境之上创建

  <!--定义别名-->
    <typeAliases>
        <typeAlias type="com.jt.pojo.User" alias="User"></typeAlias>
    </typeAliases>

1.10.2 别名包定义

 <!--定义别名-->
    <typeAliases>
        <!--定义别名-->
        <!--<typeAlias type="com.jt.pojo.User" alias="User"></typeAlias>-->
        <!--定义别名包-->
        <package name="com.jt.pojo"/>
    </typeAliases>

1.10.3 注解别名

在这里插入图片描述
3. 代码测试
在这里插入图片描述

1.10.4 Sql标签

可以通过Sql标签简化程序调用.

 <sql id="select_demo_user">
        select * from demo_user
    </sql>

    <select id="selectUserListByLike" resultType="user">
        <include refid="select_demo_user"/> where name like #{name}
    </select>

2. Mybatis参数传递

2.1 #号和$符介绍

  • #号作用:
    • 其本质为占位符赋值. 有预编译效果, 会自动添加一对引号
<select id="findUserByName" resultType="com.atguigu.mybatis.pojo.User">
        select * from demo_user where name=#{name}
</select>

在这里插入图片描述

  • $符作用:
    • 其本质为字符串拼接, 所以需要手动拼接引号, 没有预编译效果.
    • 一般用到以字段名称为参数的案例中

在这里插入图片描述
$符改进:

<select id="findUserByName" resultType="com.atguigu.mybatis.pojo.User">
	select * from demo_user where name='${name}'
</select>
  • 总结: 能用#号 不要用$

2.2 单值传递

业务说明:
1. 使用#号和$符时,如果只有一个参数时,使用任意名称都可以获取参数
2. 但是使用${} 时 不能以数字为参数
3. 使用$符时应该注意字符串参数的引号, 如果是数值类型可以直接使用$符
在这里插入图片描述

2.3 多个参数传递

业务说明: 当数据有多个参数时 默认条件下使用 param1,param2 或者arg0,arg1的方式获取数据
Mybatis多值传递说明:
Mybatis中会将多个参数自动封装为map集合,如果不指定key 则默认采用param1,param2的方式以 key=value的方式实现数据存储. 之后通过#{key}的方式实现数据获取

	<!--
        //arg1, arg0, param1, param2
    -->
    <select id="findUserByNameAndAge" resultType="User">
        <!--select * from demo_user where name=#{arg0} and age=#{arg1}-->
        select * from demo_user where name=#{param1} and age=#{param2}
    </select>

2.3 Map集合参数传递

业务说明: 如果需要自定义参数key,则可以使用Map集合的方式实现数据封装.

1.测试方法调用
在这里插入图片描述
2. Mapper接口定义

User finduserByMap(Map<String, Object> map);
  1. 映射文件实现
<!--
    User finduserByMap(Map<String, Object> map);
    -->
    <select id="finduserByMap" resultType="User">
        select * from demo_user where name=#{name} and age=#{age}
    </select>

2.4 实体对象封装数据

说明: 当有多个参数时,可以采用实体对象的方式传递数据,但是必须要求对象有get/set方法

  1. 编辑测试API
//User对象传递数据
    @Test
    public void test05() throws IOException {
        UserMapper mapper = sqlSession.getMapper(UserMapper.class);
        User user = new User();
        user.setId(null).setAge(742).setName("辟尘大王").setSex("男");
        List<User> userList = mapper.selectUser(user);
        userList.forEach(System.out::println);
    }
  1. 编辑测试接口
 List<User> selectUser(User user);
  1. 编辑测试映射文件
<select id="selectUser" resultType="User">
        select * from demo_user where name=#{name} and age=#{age} and sex=#{sex}
</select>

2.5 注解参数赋值

说明: mybatis中提供了注解@param, 可以通过该注解将数据封装为Map集合. 之后根据key进行调用
参数说明: [name, param1, age, param2]

  1. 编辑测试类
//@Param注解 实现参数传递
    @Test
    public void test06() throws IOException {
        UserMapper mapper = sqlSession.getMapper(UserMapper.class);
        String name = "辟尘大王";
        int age = 742;
        List<User> userList = mapper.selectParam(name,age);
        userList.forEach(System.out::println);
    }
  1. 编辑业务接口
List<User> selectParam(@Param("name") String name, @Param("age") int age);
  1. 编辑映射文件
 	<!--
        List<User> selectParam(@Param("name") String name, @Param("age") int age);
    -->
    <select id="selectParam" resultType="User">
        select * from demo_user where name=#{a} and age=#{age}
    </select>

2.6 package标签说明

如果有多个xml映射文件,则使用mappers中的package标签实现功能,需要注意 包路径信息应该与mapper接口路径一致.

<!--引入映射文件-->
    <mappers>

        <!--需要指定mapper接口的包路径.-->
        <!--<mapper resource="mappers/UserMapper.xml"/>-->
        <!--<package name="com.atguigu.mybatis.mapper"/>-->
        <package name="com.atguigu.mybatis.mapper"/>
    </mappers>

3. Mybatis 单表CURD操作

3.1 根据ID查询数据

3.1.1 需求说明

查询id=1的用户数据

3.1.2 编辑接口方法

在这里插入图片描述

3.1.3 编辑UserMapper.xml 映射文件

    <!--根据ID查询用户数据-->
    <select id="findUserById" parameterType="Integer" resultType="com.jt.pojo.User">
        select * from demo_user where id = #{id}
    </select>

3.1.4 编辑单元测试方法

 @Test
    public void testUserById(){
        int id = 1;
        SqlSession sqlSession = sqlSessionFactory.openSession();
        UserMapper userMapper = sqlSession.getMapper(UserMapper.class);
        User user = userMapper.findUserById(id);
        System.out.println(user);
        sqlSession.close();
    }

3.2 测试新增/修改/删除

3.2.1 编辑业务接口

public interface UserMapper {
    //查询所有的User列表信息
    List<User> findAll();
    User findUserById(Integer id);
    //实现数据新增
    int saveUser(User user);

    int updateUser(User user);

    int deleteUserById(Integer id);
}

3.2.2 编辑Mapper映射文件

<!--实现数据新增 新增成功之后自动返回影响的行数
        数据取值时 使用#{属性名} 获取数据
    -->
    <insert id="saveUser" parameterType="com.jt.pojo.User">
        insert into demo_user(id,name,age,sex) value (null,#{name},#{age},#{sex})
    </insert>
    
    <update id="updateUser" parameterType="com.jt.pojo.User">
        update demo_user set name = #{name}, age = #{age}, sex = #{sex} where id = #{id}
    </update>

    <delete id="deleteUserById" parameterType="Integer">
        delete from demo_user where id = #{id}
    </delete>

3.2.3 编辑测试方法

@Test
    public void testSaveUser(){
        User user = new User(null,"中秋节",2021,"女");
        SqlSession sqlSession = sqlSessionFactory.openSession();
        UserMapper userMapper = sqlSession.getMapper(UserMapper.class);
        int rows = userMapper.saveUser(user);
        if(rows > 0 ){
            System.out.println("事物提交");
            sqlSession.commit();
        }
        System.out.println(rows);
        sqlSession.close();
    }

    @Test
    public void testUpdateUser(){
        User user = new User(234,"中秋节BBBB",2021,"女");
        SqlSession sqlSession = sqlSessionFactory.openSession();
        UserMapper userMapper = sqlSession.getMapper(UserMapper.class);
        int rows = userMapper.updateUser(user);
        if(rows > 0 ){
            System.out.println("事物提交");
            sqlSession.commit();
        }
        System.out.println(rows);
        sqlSession.close();
    }

    @Test
    public void testDeleteUserById(){
        int id = 237;
        SqlSession sqlSession = sqlSessionFactory.openSession();
        UserMapper userMapper = sqlSession.getMapper(UserMapper.class);
        int rows = userMapper.deleteUserById(id);
        if(rows > 0 ){
            System.out.println("事物提交");
            sqlSession.commit();
        }
        System.out.println(rows);
        sqlSession.close();
    }

3.3 利用Map查询数据

3.3.1 业务需求

需求: 查询age >= 18岁 age<= 100岁的用户

3.3.2 编辑业务接口

在这里插入图片描述

3.3.3 编辑映射文件

<!--特殊转义字符
        > &gt;
        < &lt;
        & &amp;
        万能转义标签   <![CDATA[ 需要转义的内容 ]]>
    -->
    <select id="findUserListByAge" parameterType="map" resultType="com.jt.pojo.User">
        select * from demo_user where age >= #{minAge} and age &lt;= #{maxAge}
    </select>

3.3.4 编辑测试代码

/**
     * 查询age>=18 age<=100岁的用户
     */
    @Test
    public void testSelectUserListByAge(){
        SqlSession sqlSession = sqlSessionFactory.openSession();
        UserMapper userMapper = sqlSession.getMapper(UserMapper.class);
        Map map = new HashMap();
        map.put("minAge",18);
        map.put("maxAge",100);
        List<User> userList = userMapper.findUserListByAge(map);
        System.out.println(userList);
    }

3.4 查询结果 返回值为Map

说明: 有时可能找不到适合封装数据的对象,则可以使用Map集合实现结果集接收, 但是需要注意 返回值结果为一条时 使用map集合封装, 如果记录有多条 使用List集合封装
查询条件1: 查询Id=2的数据,返回值Map

查询条件2: 查询所有数据,返回值Map 接收数据List<Map<k,v>>
查询条件3: 查询所有数据,返回值Map 接收数据Map Map<key: Map<>>

3.4.1 编辑测试类

 	@Test
    public void test01() throws IOException {
        UserMapper mapper = sqlSession.getMapper(UserMapper.class);
        Map<String,Object> map = mapper.findMap();
        map.forEach((k,v) -> {
            System.out.println(k+":"+v);
        });
    }

    @Test
    public void test02() throws IOException {
        UserMapper mapper = sqlSession.getMapper(UserMapper.class);
        List<Map<String,Object>> list = mapper.findMapList();
        list.forEach(user -> {
            System.out.println(user);
        });
    }
    
	@Test
    public void test03() throws IOException {
        UserMapper mapper = sqlSession.getMapper(UserMapper.class);
        Map map = mapper.findUserToMap();
        map.forEach((k,v) -> {
            System.out.println(k+":"+v);
        });
    }

3.4.2 编辑接口

	public interface UserMapper {
	
	    //将user结果使用map类型返回
	    Map<String, Object> findMap();
	    List<Map<String, Object>> findMapList();
	    //通过关键字 实现数据查询
	    @MapKey("id")
    	Map findUserToMap();
	}

3.4.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">
<mapper namespace="com.atguigu.mybatis.mapper.UserMapper">
	    <select id="findMap" resultType="map">
	        select * from demo_user where id=2
	    </select>
		<select id="findMap" resultType="map">
	        select * from demo_user where id=2
	    </select>
	    <select id="findMapList" resultType="map">
	        select * from demo_user
	    </select>
		<select id="findUserToMap" resultType="map">
	        select * from demo_user
	    </select>
</mapper>

3.5 主键自动回显

当开启主键自增时, 则通过对象的方式获取主键自增的属性

3.5.1 编辑测试类

@Test
    public void test04() throws IOException {
        UserMapper mapper = sqlSession.getMapper(UserMapper.class);
        User user = new User();
        user.setSex("女");
        user.setName("Mybatis测试案例");
        user.setAge(100);
        int id = mapper.insertUser(user);
        sqlSession.commit();
        System.out.println("动态获取返回值:"+id);
        System.out.println("动态获取ID主键信息:"+user.getId());
    }

3.5.2 编辑测试接口

int insertUser(User user);

3.5.3 编辑xml映射文件

	<!--
        useGeneratedKeys="true"  开启主键自增操作
        keyProperty="id" 将主键为属性赋值.
    -->
    <insert id="insertUser" useGeneratedKeys="true" keyProperty="id">
        insert into demo_user values (null,#{name},#{age},#{sex})
    </insert>

3.6 模糊查询用法

3.6.1 业务需求

查询name属性中包含"君"的数据

3.6.2 业务接口

 List<User> selectUserListByLike(Map map);

3.6.3 编辑xml映射文件

 <!--<select id="selectUserListByLike" resultType="com.jt.pojo.User">
        select * from demo_user where name like "%"#{name}"%"
    </select>-->
    <select id="selectUserListByLike" resultType="com.jt.pojo.User">
        select * from demo_user where name like #{name}
    </select>

3.6.4 编辑测试方法

/**
     * 查询 name中包含'君'字的数据
     */
    @Test
    public void testSelectUserListByLike(){
        SqlSession sqlSession = sqlSessionFactory.openSession();
        UserMapper userMapper = sqlSession.getMapper(UserMapper.class);
        Map map = new HashMap();
        //map.put("name","君");
        map.put("name","%君%");
        List<User> userList = userMapper.selectUserListByLike(map);
        System.out.println(userList);
    }

3.7 Mybatis 集合参数写法 list/array/map

3.7.1 业务说明

当mybaits需要批量操作时,需要使用list/array/或者map进行数据封装

3.7.1 编辑接口

 void deleteIds(List list);

3.7.2 编辑xml映射文件

<delete id="deleteIds" parameterType="list">
        delete from demo_user where id in
            <foreach collection="list" item="id" open="(" close=")" separator=",">
                #{id}
            </foreach>
 </delete>

如果是批量更新/新增等操作 则需要添加特定属性: 关键词: allowMultiQueries=true

mysql.url=jdbc:mysql://localhost:3306/atweb?serverTimezone=UTC&allowMultiQueries=true&rewriteBatchedStatements=true&characterEncoding=utf-8

3.8 动态Sql-where条件

3.8.1 编辑测试方法

/*动态Sql*/
    @Test
    public void testSelect(){
        SqlSession sqlSession = sqlSessionFactory.openSession();
        UserMapper userMapper = sqlSession.getMapper(UserMapper.class);
        User user = new User();
        user.setName("王昭君");
        List<User> userList = userMapper.selectByUser(user);
        System.out.println(userList);
    }

3.8.2 映射方法

<select id="selectByUser" parameterType="user" resultType="user">
        select * from demo_user
        <where>
            <if test="name !=null"> name = #{name}</if>
            <if test="sex !=null">  and sex = #{sex}</if>
            <if test="age !=null">  and age = #{age}</if>
            <if test="sex !=null">  and sex = #{sex}</if>
        </where>
    </select>

3.9 动态Sql-set条件

3.9.1 编辑测试方法

	/*动态Sql 更像操作
    * 修改ID=236的用户数据 名称改为张三,age=18,sex=女
    * */
    @Test
    public void testUpdate(){
        SqlSession sqlSession = sqlSessionFactory.openSession();
        UserMapper userMapper = sqlSession.getMapper(UserMapper.class);
        User user = new User(236,"张三",18,"女");
        int rows = userMapper.updateUserSet(user);
        if(rows > 0){
            sqlSession.commit();
        }
        sqlSession.close();
    }

3.9.2 映射方法

	<update id="updateUserSet" parameterType="user">
        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.10 trim关键字

说明: 如果需要去掉额外的关键字 则建议使用trim关键字
语法说明:
- prefix=“where” 添加前缀
- prefixOverrides=“and|or” 去掉前边的关键字 如果有多个使用|线隔开
- suffix=“;” 为后缀添加数据
- suffixOverrides=“and|or” 去掉后边的关键字 如果有多个使用|线隔开

3.10.1 编辑测试类

 @Test
    public void testTrim(){
        UserMapper mapper = sqlSession.getMapper(UserMapper.class);
        User user = new User(149,null, null,"女");
        List<User> list = mapper.findTrim(user);
        System.out.println(list);
    }

3.10.2 编辑映射文件

 <select id="findTrim" resultType="User">
        select * from demo_user
        <trim prefix="where" prefixOverrides="and|or" suffix=";" suffixOverrides="and|or">
            <if test="id !=null"> and id=#{id} </if>
            <if test="name !=null">and name=#{name} </if>
            <if test="sex !=null">and sex = #{sex} </if>
            <if test="age !=null">and age = #{age} </if>
        </trim>
    </select>

3.11 动态Sql-choose、when、otherwise

3.11.1 业务需求说明

说明: 如果不想使用所有的条件可以使用choose 类似于java中的switch 语法
如果name有值,则按照name查询,否则按照sex查询数据.

3.11.2 编辑测试类

 @Test
    public void selectChoose(){
        SqlSession sqlSession = sqlSessionFactory.openSession();
        UserMapper userMapper = sqlSession.getMapper(UserMapper.class);
        User user = new User(null,null,null,"男");
        List<User> list = userMapper.selectChoose(user);
        System.out.println(list);
    }

3.11.3 编辑xml映射文件

<!--其中的用法类似于switch-->
    <select id="selectChoose" resultType="User">
        select * from demo_user
        <where>
            <choose>
                <when test="name !=null">
                    name = #{name}
                </when>
                <otherwise>
                    sex = #{sex}
                </otherwise>
            </choose>
        </where>
    </select>

3.12 resultMap介绍

3.12.1 需求说明

当表中的字段与POJO中的属性不能完全匹配时, 则需要使用resultMap映射.

3.12.2 表设计说明

在这里插入图片描述

3.12.3 编辑POJO对象

在这里插入图片描述

3.12.4 编辑测试方法

 @Test
    public void selectDog(){
        SqlSession sqlSession = sqlSessionFactory.openSession();
        DogMapper dogMapper = sqlSession.getMapper(DogMapper.class);
        List<Dog> dogList = dogMapper.findAll();
        System.out.println(dogList);
    }

3.12.5 编辑xml映射文件

 <!--
        autoMapping: 如果字段与名称相同,是否自动映射,  默认值为true 旧版本为false
        id: resultMap的主键标识 可以复用
    -->
    <resultMap id="dogRM" type="Dog" autoMapping="false">
        <id column="dog_id" property="dogId"></id>
        <result column="dog_name" property="dogName"/>
    </resultMap>


    <select id="findAll" resultMap="dogRM">
        select * from demo_dog
    </select>

3.13 开启驼峰规则映射

可以通过settings设置 是否开启驼峰规则映射
官网: https://mybatis.org/mybatis-3/zh/configuration.html#settings

 	<settings>
        <!--是否开启驼峰命名自动映射,即从经典数据库列名 A_COLUMN 映射到经典 Java 属性名 aColumn。-->
        <setting name="mapUnderscoreToCamelCase" value="true"/>
    </settings>

3.14 Mybatis注解开发(扩展)

3.14.1 常用注解

使用注解来映射简单语句会使代码显得更加简洁,但对于稍微复杂一点的语句,Java 注解不仅力不从心,还会让你本就复杂的 SQL 语句更加混乱不堪。 因此,如果你需要做一些很复杂的操作,最好用 XML 来映射语句。

3.14.2 常用注解

@Select(“select * from demo_user”)
@Update()
@Delete()
@Insert()
List findAll()

3.14.3 Mybatis绑定Mapper接口

在这里插入图片描述

3.14.4 单元测试

@Test
    public void selectAnno(){
        SqlSession sqlSession = sqlSessionFactory.openSession();
        UserMapper2 userMapper2 = sqlSession.getMapper(UserMapper2.class);
        System.out.println(userMapper2.findAll());
    }

注意事项: 多个参数调用时注意数据封装

    @Select("select * from demo_user where name = #{name} and sex = #{sex}")
    List<User> findUserByNS(@Param("name") String name,@Param("sex") String sex);

4. Mybatis 关联关系

4.1 常见关联关系

1.一对一 一个员工对应一个部门
2.一对多 一个部门对应多个员工
3.多对多 一个学生对应多个老师, 一个老师对应多个老师

4.2 一对一封装

4.2.1 表结构封装

说明: 一个员工对应一个部门.
表设计如下:
1.user表:
在这里插入图片描述
2. 部门表:
在这里插入图片描述

4.2.2 POJO对象封装

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

package com.jt.pojo;

import lombok.AllArgsConstructor;
import lombok.Data;
import lombok.NoArgsConstructor;
import lombok.experimental.Accessors;

import java.io.Serializable;

@Data
@Accessors(chain = true)
@NoArgsConstructor
@AllArgsConstructor
public class Dept implements Serializable {

    private Integer deptId;
    private String deptName;
}

4.2.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.jupiter.api.BeforeEach;
import org.junit.jupiter.api.Test;

import java.io.IOException;
import java.io.InputStream;
import java.util.List;

public class TestMybatis {

    private SqlSessionFactory sqlSessionFactory;

    @BeforeEach
    public void init() throws IOException {
        /*创建SqlSessionFactory*/
        String resource = "mybatis/mybatis-config.xml";
        InputStream inputStream = Resources.getResourceAsStream(resource);
        sqlSessionFactory = new SqlSessionFactoryBuilder().build(inputStream);
    }

    @Test
    public void oneToOne(){
        SqlSession sqlSession = sqlSessionFactory.openSession(true);
        UserMapper userMapper = sqlSession.getMapper(UserMapper.class);
        List<User> userList = userMapper.selectList();
        System.out.println(userList);
    }

    @Test
    public void oneToOne2(){
        SqlSession sqlSession = sqlSessionFactory.openSession(true);
        UserMapper userMapper = sqlSession.getMapper(UserMapper.class);
        List<User> userList = userMapper.selectList2();
        System.out.println(userList);
    }
}

4.2.4 编辑xml映射文件

<?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">

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

    <select id="selectList" resultMap="userRM">
       select * from user
    </select>
    
    <resultMap id="userRM" type="User">
        <id property="id" column="id"></id>
        <!--如果需要封装单个对象使用association封装-->
       <association property="dept"  javaType="Dept" column="dept_id" select="selectDeptById"/>
    </resultMap>

    <select id="selectDeptById" resultMap="deptRM">
        select * from dept where dept_id = #{dept_id}
    </select>

    <resultMap id="deptRM" type="Dept">
        <id property="deptId" column="dept_id"></id>
        <result property="deptName" column="dept_name"></result>
    </resultMap>

    <select id="selectList2" resultMap="userRM2">
        SELECT u.id,u.name,u.age,d.dept_id,d.dept_name FROM
            USER u
                LEFT JOIN
            dept d
            ON
                u.dept_id = d.dept_id
    </select>
    <resultMap id="userRM2" type="User" autoMapping="true">
        <!--结果集自动映射-->
        <association property="dept" javaType="Dept">
            <id property="deptId" column="dept_id"></id>
            <result property="deptName" column="dept_name"></result>
        </association>
    </resultMap>
</mapper>

4.3 一对多封装

4.3.1 封装POJO对象

@Data
@Accessors(chain = true)
@NoArgsConstructor
@AllArgsConstructor
public class Dept implements Serializable {

    private Integer deptId;
    private String deptName;
    //一个部门下有多个用户.
    private List<User> lists;
}

4.3.2 编辑测试文件

  @Test
    public void oneToMore(){
        //自动提交事务
        SqlSession sqlSession = sqlSessionFactory.openSession(true);
        DeptMapper deptMapper = sqlSession.getMapper(DeptMapper.class);
        List<Dept> list = deptMapper.findAll();
        System.out.println(list);
        sqlSession.close();
    }

    /*使用子查询的方式获取数据*/
    @Test
    public void oneToMore2(){
        //自动提交事务
        SqlSession sqlSession = sqlSessionFactory.openSession(true);
        DeptMapper deptMapper = sqlSession.getMapper(DeptMapper.class);
        List<Dept> list = deptMapper.findAll2();
        System.out.println(list);
        sqlSession.close();
    }

4.3.3 编辑xml映射文件

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

    <select id="findAll" resultMap="deptRM">
        SELECT d.dept_id,d.dept_name,u.id,u.name,u.age
        FROM dept d,USER u
        WHERE  u.dept_id = d.dept_id
    </select>

    <resultMap id="deptRM" type="Dept">
        <id property="deptId" column="dept_id"></id>
        <result property="deptName" column="dept_name"></result>
        <collection property="lists" ofType="User" autoMapping="true">
            <!--<id property="id" column="id"></id>
            <result property="name" column="name"></result>
            <result property="age" column="age"></result>-->
        </collection>
    </resultMap>

    <!--使用关联查询的方式获取数据-->
    <select id="findAll2" resultMap="deptRM2">
        select * from dept
    </select>
    <resultMap id="deptRM2" type="Dept">
        <id property="deptId" column="dept_id"></id>
        <result property="deptName" column="dept_name"></result>
        <collection property="lists" ofType="User" column="dept_id" select="findUser"></collection>
    </resultMap>

    <select id="findUser" resultType="User">
        select * from user where dept_id = #{dept_id}
    </select>
</mapper>

4.3.4 Mapper映射文件包扫描

说明: 编辑mybatis-config.xml配置文件 通过package属性定义配置信息
要求: 包路径必须与mapper接口的路径相同

	<mappers>
        <package name="com.atguigu.mybatis.mapper"/>
    </mappers>

在这里插入图片描述

4.4 延时加载测试

4.4.1 延时加载配置

说明: 如果在进行子查询时 如果不需要立即获取子查询数据 则可以使用懒加载
配置: 编辑mybaits-config.xml配置文件

	<settings>
        <!--开启驼峰映射  字段dog_id 可以自动映射到 dogId -->
        <setting name="mapUnderscoreToCamelCase" value="true"/>
        <setting name="lazyLoadingEnabled" value="true"/>
    </settings>

注意事项:
如果没有查询子数据时,则子查询不会执行

 @Test
    public void testFind2(){
        DogMapper mapper = sqlSession.getMapper(DogMapper.class);
        List<Dog> list = mapper.selectDog();
        list.get(0).getDogName();
        //其中list.toString 中调用了子对象 所以会进行子查询
        System.out.println(list);
    }

4.4.2 立即查询操作

  • fetchType=“eager” 懒加载失效
  • fetchType=“lazy” 懒加载有效
 <!--
        mybatis where条件子查询
    -->
    <select id="selectDog" resultMap="dogSelectRM">
        select * from dog
    </select>
    <!--
        select: 执行子查询的操作
        column: 主表与从表的关联字段
    -->
    <resultMap id="dogSelectRM" type="Dog" autoMapping="true">
        <id property="dogId" column="dog_id"/>
        <association property="dept" javaType="Dept" select="selectDept" column="dept_id" fetchType="eager"/>
    </resultMap>
    <!--
        子表获取主表中关联字段的值  每次一个
    -->
    <select id="selectDept" resultType="Dept">
        select * from dept where dept_id=#{deptId}
    </select>

5 Mybatis 缓存

5.1 缓存概念

如果有大量相同的请求查询数据库,则数据库需要执行多次重复的sql,那么并发压力高,查询效率低. 如果引入缓存机制,则可以极大的提升用户的查询的效率
在这里插入图片描述

5.2 Mybatis的缓存

  1. Mybatis中自身提供了缓存机制,可以极大的提高查询效率.
  2. Mybatis系统中默认定义了两级缓存: 一级缓存二级缓存
  3. Mybatis默认条件下只开启一级缓存, 一级缓存是sqlSession级别的, 在同一个sqlSession中查询数据可以共享数据.
  4. 二级缓存默认开启. 二级缓存是SqlSessionFactory级别. 同一个工厂创建多个sqlSession共享数据.
  5. Mybatis 也提供了第三方Cache接口,整合第三方缓存(了解)

5.3 一级缓存测试

经过测试发现 业务方法查询了多次,但是Sql语句执行了一次.

 /*使用子查询的方式获取数据*/
    /*使用子查询的方式获取数据*/
    @Test
    public void testCache1(){
        SqlSession sqlSession = sqlSessionFactory.openSession(true);
        DeptMapper deptMapper = sqlSession.getMapper(DeptMapper.class);
        List<Dept> list1 = deptMapper.findAll2();
        List<Dept> list2 = deptMapper.findAll2();
        List<Dept> list3 = deptMapper.findAll2();
        //测试结果为true,表示引用对象是同一个.
        System.out.println(list1 == list2);
    }

在这里插入图片描述

5.4 二级缓存测试

5.4.1 开启二级缓存

说明: 通过cache标签可以开启二级缓存
在这里插入图片描述

5.4.2 二级缓存测试

 /*使用子查询的方式获取数据*/
    @Test
    public void testCache2(){
        SqlSession sqlSession = sqlSessionFactory.openSession(true);
        DeptMapper deptMapper = sqlSession.getMapper(DeptMapper.class);
        List<Dept> list1 = deptMapper.findAll2();
        //只有一级缓存关闭之后,二级缓存才能生效
        sqlSession.close();

        SqlSession sqlSession2 = sqlSessionFactory.openSession(true);
        DeptMapper deptMapper2 = sqlSession2.getMapper(DeptMapper.class);
        List<Dept> list2 = deptMapper2.findAll2();
        sqlSession2.close();
    }

5.5 Mybatis 缓存测试

5.5.1 一级缓存测试

说明: Mybatis默认的一级缓存是开启的. 但是在SpringBoot整合之后.每次mapper调用都是一个全新的SqlSession.所以导致一级缓存不生效
解决方案: 添加事务注解 使用同一个SqlSession

package com.jt;

import com.jt.mapper.UserMapper;
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;

@SpringBootTest
public class TestMybatis {

    @Autowired
    private UserMapper userMapper;

    //springboot整合mybatis 开启事务之后一级缓存有效.
    //否则每次调用都是一个新的sqlSession
    @Test
    @Transactional
    public void test01(){
        userMapper.findAll();
        userMapper.findAll();
        userMapper.findAll();
    }
}

5.5.2 二级缓存测试

说明: 在xml映射文件中 添加缓存标签

<?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">
<mapper namespace="com.jt.mapper.UserMapper">

    <!--启用二级缓存-->
    <cache></cache>


    <select id="findAll" resultType="User">
        select * from demo_user
    </select>
</mapper>

5.5.3 二级注解缓存写法

说明: 二级缓存写法 xml配置文件和注解写法只能二选一 不能同时生效.

package com.jt.mapper;

import com.jt.pojo.User;
import org.apache.ibatis.annotations.CacheNamespace;
import org.apache.ibatis.annotations.Select;

import java.util.List;

/**
 * @author 刘昱江
 * 时间 2021/5/9
 */
@CacheNamespace
public interface UserMapper {
    List<User> findAll();
    @Select("select * from demo_user")
    List<User> getUserAnno();
}

5.5.4 二级缓存相关配置

<cache
  eviction="FIFO"
  flushInterval="60000"
  size="512"
  readOnly="true"/>
  • 缓存策略:
    LRU – 最近最少使用:移除最长时间不被使用的对象。 默认的清除策略是 LRU。
    FIFO – 先进先出:按对象进入缓存的顺序来移除它们。
    SOFT – 软引用:基于垃圾回收器状态和软引用规则移除对象。
    WEAK – 弱引用:更积极地基于垃圾收集器状态和弱引用规则移除对象。

  • flushInterval(刷新间隔)属性可以被设置为任意的正整数,设置的值应该是一个以毫秒为单位的合理时间量。 默认情况是不设置,也就是没有刷新间隔,缓存仅仅会在调用语句时刷新。

  • size(引用数目)属性可以被设置为任意正整数,要注意欲缓存对象的大小和运行环境中可用的内存资源。默认值是 1024。

  • eadOnly(只读)属性可以被设置为 true 或 false。只读的缓存会给所有调用者返回缓存对象的相同实例。 因此这些对象不能被修改。这就提供了可观的性能提升。而可读写的缓存会(通过序列化)返回缓存对象的拷贝。 速度上会慢一些,但是更安全,因此默认值是 false。

5.5.5 关于一级缓存和二级缓存的总结

  • 一级缓存SqlSession级别, 在同一个sqlSession内实现数据共享. 默认开启的
  • 二级缓存SqlSessionFactory级别. 由同一个SqlSessionFactory创建的SqlSession 实现数据共享. 类似于多线程操作的数据共享.
  • 二级缓存的配置: 1. 二级缓存默认全局开启 2.如果需要使用

5.6 Mybatis引入第三方缓存

5.6.1 关于缓存介绍

分布式缓存框架:我们系统为了提高系统并发和性能,一般对系统进行分布式部署(集群部署方式)不适用分布缓存, 缓存的数据在各个服务单独存储,不方便系统开发。所以要使用分布式缓存对缓存数据进行集中管理.ehcache,redis ,memcache缓存框架。Ehcache:是一种广泛使用的开源java分布式缓存。主要面向通用缓存,javaEE 和 轻量级容器。它具有内存和磁盘存储功能。被用于大型复杂分布式web application.这里的三方缓存是作为二级缓存使用的

5.6.2 引入jar包

<!-- Mybatis EHCache整合包 -->
<dependency>
    <groupId>org.mybatis.caches</groupId>
    <artifactId>mybatis-ehcache</artifactId>
    <version>1.2.1</version>
</dependency>
<!-- slf4j日志门面的一个具体实现 -->
<dependency>
    <groupId>ch.qos.logback</groupId>
    <artifactId>logback-classic</artifactId>
    <version>1.2.3</version>
</dependency>

5.6.3 编写ehcache.xml配置文件

<?xml version="1.0" encoding="utf-8" ?>
<ehcache xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
         xsi:noNamespaceSchemaLocation="../config/ehcache.xsd">
    <!-- 磁盘保存路径 -->
    <diskStore path="D:\atguigu\ehcache"/>

    <defaultCache
            maxElementsInMemory="1000"
            maxElementsOnDisk="10000000"
            eternal="false"
            overflowToDisk="true"
            timeToIdleSeconds="120"
            timeToLiveSeconds="120"
            diskExpiryThreadIntervalSeconds="120"
            memoryStoreEvictionPolicy="LRU">
    </defaultCache>
</ehcache>

<!-- 
属性说明:
 diskStore:指定数据在磁盘中的存储位置。
 defaultCache:当借助CacheManager.add("demoCache")创建Cache时,EhCache便会采用<defalutCache/>指定的的管理策略
 
以下属性是必须的:
 maxElementsInMemory - 在内存中缓存的element的最大数目 
 maxElementsOnDisk - 在磁盘上缓存的element的最大数目,若是0表示无穷大
 eternal - 设定缓存的elements是否永远不过期。如果为true,则缓存的数据始终有效,如果为false那么还要根据timeToIdleSeconds,timeToLiveSeconds判断
 overflowToDisk - 设定当内存缓存溢出的时候是否将过期的element缓存到磁盘上
 
以下属性是可选的:
 timeToIdleSeconds - 当缓存在EhCache中的数据前后两次访问的时间超过timeToIdleSeconds的属性取值时,这些数据便会删除,默认值是0,也就是可闲置时间无穷大
 timeToLiveSeconds - 缓存element的有效生命期,默认是0.,也就是element存活时间无穷大
 diskSpoolBufferSizeMB 这个参数设置DiskStore(磁盘缓存)的缓存区大小.默认是30MB.每个Cache都应该有自己的一个缓冲区.
 diskPersistent - 在VM重启的时候是否启用磁盘保存EhCache中的数据,默认是false。
 diskExpiryThreadIntervalSeconds - 磁盘缓存的清理线程运行间隔,默认是120秒。每隔120s,相应的线程会进行一次EhCache中数据的清理工作
 memoryStoreEvictionPolicy - 当内存缓存达到最大,有新的element加入的时候, 移除缓存中element的策略。默认是LRU(最近最少使用),可选的有LFU(最不常使用)和FIFO(先进先出)
 -->

5.6.4 配置Cache标签

<!--使用第三方二级缓存-->
<cache type="org.mybatis.caches.ehcache.EhcacheCache"></cache>

5.7 逆向工程实现

5.7.1 逆向工程介绍

MyBatis Generator: 简称MBG,是一个专门为MyBatis框架使用者定制的代码生成器,可以快速的根据表生成对应的映射文件,接口,以及bean类。支持基本的增删改查,以及QBC风格的条件查询。但是表连接、存储过程等这些复杂sql的定义需要我们手工编写

文档地址: http://www.mybatis.org/generator/
官方工程地址: https://github.com/mybatis/generator/releases

5.7.2 添加插件

<!-- 控制Maven在构建过程中相关配置 -->
    <build>

        <!-- 构建过程中用到的插件 -->
        <plugins>

            <!-- 具体插件,逆向工程的操作是以构建过程中插件形式出现的 -->
            <plugin>
                <groupId>org.mybatis.generator</groupId>
                <artifactId>mybatis-generator-maven-plugin</artifactId>
                <version>1.3.0</version>
				<!--允许覆盖原始数据-->
                <configuration>
                    <overwrite>true</overwrite>
                </configuration>	
                <!-- 插件的依赖 -->
                <dependencies>

                    <!-- 逆向工程的核心依赖 -->
                    <dependency>
                        <groupId>org.mybatis.generator</groupId>
                        <artifactId>mybatis-generator-core</artifactId>
                        <version>1.3.2</version>
                    </dependency>

                    <!-- 数据库连接池 -->
                    <dependency>
                        <groupId>com.mchange</groupId>
                        <artifactId>c3p0</artifactId>
                        <version>0.9.2</version>
                    </dependency>

                    <!-- MySQL驱动 -->
                    <dependency>
                        <groupId>mysql</groupId>
                        <artifactId>mysql-connector-java</artifactId>
                        <version>8.0.16</version>
                    </dependency>
                </dependencies>
            </plugin>
        </plugins>
    </build>

5.7.3 编辑配置文件

说明: 编辑generatorConfig.xml的配置文件

	<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE generatorConfiguration
        PUBLIC "-//mybatis.org//DTD MyBatis Generator Configuration 1.0//EN"
        "http://mybatis.org/dtd/mybatis-generator-config_1_0.dtd">
<generatorConfiguration>
    <!--
            targetRuntime: 执行生成的逆向工程的版本
                    MyBatis3Simple: 生成基本的CRUD(清新简洁版)
                    MyBatis3: 生成带条件的CRUD(奢华尊享版)
     -->
    <context id="DB2Tables" targetRuntime="MyBatis3">
        <commentGenerator>
            <!-- 是否去除自动生成的注释 true:是 : false:否 -->
            <property name="suppressAllComments" value="true"/>
        </commentGenerator>

        <!-- 数据库的连接信息 -->
        <jdbcConnection driverClass="com.mysql.cj.jdbc.Driver"
                        connectionURL="jdbc:mysql://localhost:3306/atweb?serverTimezone=UTC&amp;allowMultiQueries=true&amp;rewriteBatchedStatements=true&amp;characterEncoding=utf-8"
                        userId="root"
                        password="root">
            <property name="nullCatalogMeansCurrent" value="true"/>
        </jdbcConnection>
        <!-- javaBean的生成策略-->
        <javaModelGenerator targetPackage="com.atguigu.mybatis.bean" targetProject=".\src\main\java">
            <property name="enableSubPackages" value="true" />
            <property name="trimStrings" value="true" />
        </javaModelGenerator>

        <!-- SQL映射文件的生成策略 -->
        <sqlMapGenerator targetPackage="com.atguigu.mybatis.mapper"  targetProject=".\src\main\resources">
            <property name="enableSubPackages" value="true" />
        </sqlMapGenerator>

        <!-- Mapper接口的生成策略 -->
        <javaClientGenerator type="XMLMAPPER" targetPackage="com.atguigu.mybatis.mapper"  targetProject=".\src\main\java">
            <property name="enableSubPackages" value="true" />
        </javaClientGenerator>
        <!-- 逆向分析的表 -->
        <!-- tableName设置为%号,可以对应所有表,此时不写domainObjectName -->
        <!-- domainObjectName属性指定生成出来的实体类的类名 -->
        <table tableName="demo_user" domainObjectName="User"/>
       <!-- <table tableName="%"/>-->
    </context>
</generatorConfiguration>

5.8 关于MybatisGenerator API介绍

5.8.1 新增操作实现

@Test
    public void test01(){
        UserMapper mapper = sqlSession.getMapper(UserMapper.class);
        User user = new User();
        user.setId(null);
        user.setName(null);
        user.setAge(null);
        user.setSex("男");
        //为所有字段添加数据 包括null值
        int rows1 = mapper.insert(user);
        //为其中非null数据添加赋值操作  选择性添加
        int rows2 = mapper.insertSelective(user);
    }

在这里插入图片描述

5.8.2 动态修改操作

	@Test
    public void testUpdate(){
        UserMapper mapper = sqlSession.getMapper(UserMapper.class);
        User user = new User(152,"李四",15,"男");
        mapper.updateByPrimaryKey(user);
        User user2 = new User(152,null,null,"男");
        mapper.updateByPrimaryKeySelective(user2);
    }

5.8.3 删除操作

 @Test
    public void testDelete(){
        UserMapper mapper = sqlSession.getMapper(UserMapper.class);
        mapper.deleteByPrimaryKey(157);
    }

5.8.4 查询操作

	@Test
    public void testSelectByAge(){
        UserMapper mapper = sqlSession.getMapper(UserMapper.class);
        UserExample userExample = new UserExample();
        //大于等于
        //userExample.createCriteria().andAgeGreaterThanOrEqualTo(40);
        //age区间
        //userExample.createCriteria().andAgeBetween(40,200);
        Integer[] ids = new Integer[]{3000,4000,5000};
        userExample.createCriteria().andAgeIn(Arrays.asList(ids));
        List<User> users = mapper.selectByExample(userExample);
        System.out.println(users);
    }

6 Mybatis 分页插件

6.1 分页插件介绍

分页查询是业务中常用的操作, mybatis为分页提供了强大的支持 pagehelper

6.2 导入jar包

	<dependency>
	    <groupId>com.github.pagehelper</groupId>
	    <artifactId>pagehelper</artifactId>
	    <version>5.2.0</version>
	</dependency>

6.3 添加插件

注意分页插件 pagehelper的位置

 	 <!--指定别名-->
    <typeAliases>
        <!--为指定路径的类型  起别名-->
        <!--<typeAlias type="com.atguigu.mybatis.pojo.User" alias="Dog"/>-->
        <!--通过定义别名包 则指定别名就是类名  运行时会通过该路径扫描特定的注解-->
       <package name="com.atguigu.mybatis.pojo"/>
    </typeAliases>

    <plugins>
        <plugin interceptor="com.github.pagehelper.PageInterceptor"></plugin>
    </plugins>

6.4 分页关键字说明

  • pageSize:每页显示的条数

  • pageNum:当前页的页码

  • index:当前页的起始索引,index=(pageNum-1)*pageSize

  • count:总记录数

  • totalPage:总页数

  • totalPage = count / pageSize;

	if(count  % pageSize != 0){
​		totalPage  += 1;
	}

6.5 分页API 讲解

6.5.1 入门案例

 @Test
    public void testSelect(){
        UserMapper mapper = sqlSession.getMapper(UserMapper.class);
        PageHelper pageHelper = new PageHelper();
        int pageNum = 1;    //第一页
        int pageSize = 5;
        Page<User> page = PageHelper.startPage(pageNum, pageSize);
        List<User> list = mapper.selectAll();
        list.forEach(System.out::println);

        //分页中的所有数据都在其中
        PageInfo<User> pageInfo = new PageInfo<>(list,5);
        System.out.println(pageInfo);
    }

6.5.2 分页查询

在查询功能之前使用PageHelper.startPage(int pageNum, int pageSize)开启分页功能

pageNum:当前页的页码

pageSize:每页显示的条数

6.5.3 分页对象

在查询获取list集合之后,使用PageInfo<T> pageInfo = new PageInfo<>(List<T> list, int navigatePages)获取分页相关数据

list:分页之后的数据

navigatePages:导航分页的页码数

6.5.4 分页对象详情

分页相关数据

PageInfo{

pageNum=8, pageSize=4, size=2, startRow=29, endRow=30, total=30, pages=8,

list=Page{count=true, pageNum=8, pageSize=4, startRow=28, endRow=32, total=30,

pages=8, reasonable=false, pageSizeZero=false},

prePage=7, nextPage=0, isFirstPage=false, isLastPage=true, hasPreviousPage=true,

hasNextPage=false, navigatePages=5, navigateFirstPage4, navigateLastPage8,

navigatepageNums=[4, 5, 6, 7, 8]

}

pageNum:当前页的页码

pageSize:每页显示的条数

size:当前页显示的真实条数

total:总记录数

pages:总页数

prePage:上一页的页码

nextPage:下一页的页码

isFirstPage/isLastPage:是否为第一页/最后一页

hasPreviousPage/hasNextPage:是否存在上一页/下一页

navigatePages:导航分页的页码数

navigatepageNums:导航分页的页码,[1,2,3,4,5]

Logo

有“AI”的1024 = 2048,欢迎大家加入2048 AI社区

更多推荐