MyBatis一看就会

什么是MyBatis?

  1. MyBatis是一个半ORM框架,内部封装了JDBC,开发时只需要关注SQL语句本身。不需要花费精力取加载驱动,创建连接,创建Statement的复杂的过程。
  2. MyBatis可以通过XML或注解的方式来配置和映射原生信息,将POJO映射成数据库中的记录,几乎避免了所有的JDBC代码和手动设置参数,以及获取结果集。
  3. MyBatis可以通过XML或注解的方式来配置和映射原生信息。通过Java对象和Statement中的SQL语句的动态参数进行映射,生成最终要执行的SQL语句。最后由MyBatis框架执行SQL语句,并将结果映射为Java对象返回。

MyBatis的优点和缺点

优点

  1. MyBatis基于SQL语句编程,相当灵活;不会对应用程序或数据库现有的设计造成任何影响;SQL写在XML文件中,解除程序于代码的耦合,方便统一管理;提供XML标签,支持编写动态SQL语句,并可以重用。
  2. MyBatis于JDBC相比,减少了50%以上的代码量,消除了大量重复代码。
  3. MyBatis能够很好的于各种数据库相兼容。
  4. MyBatis能够于Spring框架很好的集成。
  5. MyBatis提供映射标签,支持对象与数据库字段的ORM映射;提供对象关系映射标签,支持对象关系组件维护。

缺点

  1. SQL语句的编写工作量大
  2. SQL语句依赖于数据库,导致数据库移植性差,不能随便更换数据库

MyBatis整体架构和运行流程

MyBatis的整体构造由数据源配置文件SQL映射文件会话工厂会话执行器底层封装对象组成。

1、数据源配置文件

        通过配置的方式将数据库的配置信息从应用程序中独立出来,由独立的模块管理和配置。Mybatis的数据源配置文件包含数据库驱动、数据库连接地址、用户名密码、事务管理等,还可以配置连接池的连接数、空闲时间等。

mapper-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=""/>
                <property name="url" value=""/>
                <property name="username" value=""/>
                <property name="password" value=""/>
            </dataSource>
        </environment>
    </environments>
    <mappers>
        <mapper resource="org/mybatis/example/BlogMapper.xml"/>
    </mappers>
</configuration>

mapper文件映射

mapper标签中的resource属性参数是mapper文件的相对路径

使用相对路径引用mapper文件每次只能引用一个mapper文件;如果需要引用多个mapper文件,那么每个文件都要使用mapper标签中的resource属性引用mapper文件,不推荐使用此方式

<!-- 
    方式一:使用相对类路径引用mapper配置文件
-->
<mappers>
    <mapper resource="org/mybatis/example/BlogMapper.xml"/>
</mappers>

mapper标签中的class属性mapper文件的完整限定名

使用该方式时MyBatis会class属性用对象的mapper文件接口,然后还会去加载该接口同目录下的同名的mapper.xml文件

<!--
    方式二:使用映射器接口,实现类的完全限定名
-->
<mappers>
    <mapper class="org.mybatis.example.BlogMapper"/>
</mappers>

package标签批量注册mapper接口,根据name属性中的参数路径,将指定文件下的mapper.xml文件全部注册为映射器。

注意:

  1. 包名和接口所在包,名称要一致
  2. mapper.xml文件的名称要和接口名称一致
  3. 在”resource“下创建包使用”/“分割
<!--
    方式三:将包内的映射器接口实现全部注册为映射器
-->
<mappers>
    <package name="org.mybatis.example"/>
</mappers>

2、SQL映射文件

Mybatis中所有数据库的操作都会基于该映射文件和配置的sql语句,在这个配置文件中可以配置任何类型的sql语句。框架会根据配置文件中的参数配置,完成对sql语句以及输入输出参数的映射配置。

Mapper.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="命名空间">

<select id="方法名" resultMap="返回值类型" parameterType="参数类型">

-- sql语句

</select>

</mapper>

3.会话工厂与会话

        Mybatis中会话工厂SqlSessionFactory类可以通过加载资源文件,读取数据源配置MapConfig.xml信息,从而产生一种可以与数据库交互的会话实例SqlSession,会话实例SqlSession根据Mapper.xml文件中配置的sql,对数据库进行操作。

4.运行流程

        会话工厂SqlSessionFactory通过加载资源文件获取MapConfig.xml配置文件信息,然后生成可以与数据库交互的会话实例SqlSession。会话实例可以根据Mapper配置文件中的Sql配置去执行相应的增删改查操作。

MyBatis实现增删改查

增删改查前的准备

1、添加依赖

<?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>cn.wzw.my</groupId>
    <artifactId>MyBatisDemo03</artifactId>
    <version>1.0-SNAPSHOT</version>

    <properties>
        <maven.compiler.source>14</maven.compiler.source>
        <maven.compiler.target>14</maven.compiler.target>
        <project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
    </properties>

    <dependencies>
<!--        代码测试依赖-->
        <dependency>
            <groupId>junit</groupId>
            <artifactId>junit</artifactId>
            <version>4.12</version>
            <scope>test</scope>
        </dependency>
<!--        通过注解消除实际开发中的样板式代码-->
        <dependency>
            <groupId>org.projectlombok</groupId>
            <artifactId>lombok</artifactId>
            <version>1.18.26</version>
        </dependency>
<!--        日志依赖-->
        <dependency>
            <groupId>log4j</groupId>
            <artifactId>log4j</artifactId>
            <version>1.2.17</version>
        </dependency>
<!--        mybatis依赖-->
        <dependency>
            <groupId>org.mybatis</groupId>
            <artifactId>mybatis</artifactId>
            <version>3.5.9</version>
        </dependency>
<!--        数据库依赖-->
        <dependency>
            <groupId>mysql</groupId>
            <artifactId>mysql-connector-java</artifactId>
            <version>5.1.49</version>
        </dependency>
    </dependencies>

</project>

2、配置mapper-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>
<!--    引入数据库配置文件-->
    <properties resource="config/jdbc.properties"></properties>
    <settings>
<!--        开启驼峰命名-->
        <setting name="mapUnderscoreToCamelCase" value="true"/>
<!--        开启日志-->
        <setting name="logImpl" value="log4j"/>
    </settings>
<!--    设置别名-->
    <typeAliases>
        <package name="cn.wzw.my.entity"/>
    </typeAliases>
    <environments default="development">
        <environment id="development">
<!--            事务管理-->
            <transactionManager type="JDBC"/>
<!--            配置数据源-->
            <dataSource type="POOLED">
<!--                使用配置文件中的键,设置数据库驱动、链接地址、用户名、密码-->
                <property name="driver" value="${jdbc.driver}"/>
                <property name="url" value="${jdbc.url}"/>
                <property name="username" value="${jdbc.user}"/>
                <property name="password" value="${jdbc.password}"/>
            </dataSource>
        </environment>
    </environments>
<!--    mapper接口映射-->
    <mappers>
        <package name="cn.wzw.my.mapper"/>
    </mappers>
</configuration>

3、配置log4j.properties文件,放置在resources目录下 

log4j.rootLogger=DEBUG,Console

#Console
log4j.appender.Console=org.apache.log4j.ConsoleAppender
log4j.appender.console.Target=System.out
log4j.appender.Console.layout=org.apache.log4j.PatternLayout
log4j.appender.Console.layout.ConversionPattern=%d [%t] %-5p [%c] - %m%n

log4j.logger.org.apache=ERROR
log4j.logger.org.mybatis=ERROR
log4j.logger.org.springframework=ERROR

#这个需要
log4j.logger.log4jdbc.debug=ERROR
log4j.logger.com.gk.mapper=ERROR
log4j.logger.jdbc.audit=ERROR
log4j.logger.jdbc.resultset=ERROR
#这个打印SQL语句非常重要
log4j.logger.jdbc.sqlonly=DEBUG
log4j.logger.jdbc.sqltiming=ERROR
log4j.logger.jdbc.connection=FATAL

实现增删改查

user表


CREATE TABLE `user` (
  `uid` int(3) NOT NULL AUTO_INCREMENT COMMENT '编号',
  `user` varchar(20) NOT NULL COMMENT '用户名',
  `password` varchar(20) NOT NULL COMMENT '密码',
  `start` varchar(10) NOT NULL COMMENT '状态',
  PRIMARY KEY (`uid`)
package cn.wzw.my.entity;

import lombok.Data;

@Data
public class User {

  private long uid;
  private String user;
  private String password;
  private String start;

}

1、UserMapper接口

package cn.wzw.my.mapper;

import cn.wzw.my.entity.User;

import java.util.List;

public interface UserMapper {
    /**
     * 第一部分:实现增删改查
     */
    // 增加
    Integer insertUser(User user);
    // 修改
    Integer updateUser(User user);
    // 删除
    Integer deleteUser(Integer id);
    // 查询单条记录
    User selectUserById(Integer id);
    // 查询所有记录
    List<User> selectUserAll();
}

2、UserMapper.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="cn.wzw.my.mapper.UserMapper">

<!--
    第一部分:实现增删改查
-->
<!--    增加-->
    <insert id="insertUser">
        insert into `user` (`user`,`password`,`start`) values (#{user},#{password},#{start})
    </insert>
<!--    修改-->
    <update id="updateUser">
        update `user` set `user`=#{user} ,`password`=#{password} ,`start`=#{start} where `uid`=#{uid}
    </update>
<!--    删除-->
    <delete id="deleteUser">
        delete from `user` where `uid`=#{uid}
    </delete>
<!--    查询单条记录-->
    <select id="selectUserById" resultType="user">
        select * from `user` where `uid`=#{uid}
    </select>
<!--    查询所有记录-->
    <select id="selectUserAll" resultType="user">
        select * from `user`
    </select>
</mapper>

3、UserMapperTest测试类

package cn.wzw.my.mapper;

import cn.wzw.my.entity.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.Before;
import org.junit.Test;

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

import static org.junit.Assert.*;

public class UserMapperTest {
    SqlSessionFactory sqlSessionFactory = null;
    @Before
    public void init(){
        try {
//            Mybatis中会话工厂SqlSessionFactory类可以通过加载资源文件,读取数据源配置MapConfig.xml信息
            InputStream resource = Resources.getResourceAsStream("config/mybatis-config.xml");
            sqlSessionFactory = new SqlSessionFactoryBuilder().build(resource);
        } catch (IOException e) {
            throw new RuntimeException(e);
        }
    }

    /**
     *  第一部分:实现增删改查
     */

//    增加
    @Test
    public void insertUser() {
//        会话实例SqlSession根据Mapper.xml文件中配置的sql,对数据库进行操作。
        SqlSession sqlSession = sqlSessionFactory.openSession(true);
        User user = new User();
        user.setUser("lisi");
        user.setPassword("123456");
        user.setStart("1");
//        通过SqlSession实例对象去操作数据库,方法中的参数需要指定接口中对应的方法路径
        int result = sqlSession.insert("cn.wzw.my.mapper.UserMapper.insertUser", user);
        System.out.println(result!=0?"数据添加成功":"数据添加失败");

    }

//    修改
    @Test
    public void updateUser() {
//        获取会话实例SqlSession
        SqlSession sqlSession = sqlSessionFactory.openSession(true);
        User user = new User();
        user.setUid(1011);
        user.setUser("李四");
        user.setPassword("1008611");
        user.setStart("0");
//        通过SqlSession实例对象去操作数据库,方法中的参数需要指定接口中对应的方法路径
        int result = sqlSession.update("cn.wzw.my.mapper.UserMapper.updateUser", user);
        System.out.println(result!=0?"修改成功":"修改失败");
    }

//    删除
    @Test
    public void deleteUser() {
        SqlSession sqlSession = sqlSessionFactory.openSession(true);
//        通过SqlSession实例对象去操作数据库,方法中的参数需要指定接口中对应的方法路径
        int result = sqlSession.update("cn.wzw.my.mapper.UserMapper.deleteUser", 1011);
        System.out.println(result!=0?"删除成功":"删除失败");
    }

//    查询单条记录
    @Test
    public void selectUserById() {
        SqlSession sqlSession = sqlSessionFactory.openSession(true);
//        通过SqlSession实例对象去操作数据库,方法中的参数需要指定接口中对应的方法路径
        User user = sqlSession.selectOne("cn.wzw.my.mapper.UserMapper.selectUserById", 1010);
        System.out.println("user = " + user);
    }

//    查询所有记录
    @Test
    public void selectUserAll() {
        SqlSession sqlSession = sqlSessionFactory.openSession(true);
//        通过SqlSession实例对象去操作数据库,方法中的参数需要指定接口中对应的方法路径
        List<User> users = sqlSession.selectList("cn.wzw.my.mapper.UserMapper.selectUserAll");
        for (User user:users){
            System.out.println("user = " + user);
        }
    }

SQL语句中的#{}和${}的区别

#{}:#{}是编译预处理,MyBatis在执行SQL语句时,会将SQL语句中的#{}替换为?,然后再调用PreparedStatement中的set方法进行赋值。可以有效的方式SQL语句注入,提高安全性。

${}:${}是字符串替换,MyBatis在执行SQL语句时,会将SQL语句中的${}替换为变量的值

MyBatis获取参数的方式

  1. 接口中有单个参数
  2. 接口中有多个零散参数;MyBatis在处理多个参数是,会将多个参数保存到map集合中,会以arg0,arg1,或者param1,param2为键,以参数的位置进行存储。
  3. 将多个参数封装成实体类对象作为接口参数
  4. 将多个参数保存到Map集合中作为接口参数

1、UserMapper接口


    /**
     * 第二部分:MyBatis参数的获取方式
     * 1、接口中有单个参数
     * 2、接口中有多个零散参数
     * 3、将多个参数封装成实体类对象作为接口参数
     * 4、将多个参数保存到Map集合中作为接口参数
     */
//    1、接口中有单个参数
    User selectOne(Integer id);

//    2、接口中有多个零散参数
//    方式一
    User userAndStart1(@Param("user") String user, @Param("start") String start);
//    方式二
    User userAndStart2(String user ,String start);

//    3、将多个参数封装成实体类对象最为接口参数
    User selectUser(User user);

//    4、将多个参数保存到Map集合中作为接口参数
    User selectMap(Map map);

2、UserMapper.xml文件

<!--
    /**
     * 第二部分:MyBatis参数的获取方式
     * 1、接口中有单个参数
     * 2、接口中有多个零散参数
     * 3、将多个参数封装成实体类对象作为接口参数
     * 4、将多个参数保存到Map集合中作为接口参数
     */
-->
<!--    1、接口中有单个参数-->
    <select id="selectOne" resultType="user">
        select * from `user` where `uid`=#{uid}
    </select>
<!--    2、接口中有多个零散参数 方式一-->
    <select id="userAndStart1" resultType="user">
        select * from `user` where `user`=#{user} and `start`=#{start}
    </select>
<!--    2、接口中有多个零散参数 方式二-->
    <select id="userAndStart2" resultType="user">
        select * from `user` where `user`=#{param1} and `start`=#{param2}
    </select>
<!--    3、将多个参数封装成实体类对象最为接口参数-->
    <select id="selectUser" resultType="user">
        select * from `user` where `user`=#{user} and `start`=#{start}
    </select>
<!--    4、将多个参数保存到Map集合中作为接口参数-->
    <select id="selectMap" resultType="user">
        select * from `user` where `user`=#{user} and `start`=#{start}
    </select>

3、UserMapperTest测试类

    /**
     * 第二部分:MyBatis参数的获取方式
     * 1、接口中有单个参数
     * 2、接口中有多个零散参数
     * 3、将多个参数封装成实体类对象作为接口参数
     * 4、将多个参数保存到Map集合中作为接口参数
     */
//    1、接口中有单个参数
    @Test
    public void selectOne() {
        SqlSession sqlSession = sqlSessionFactory.openSession(true);
//        通过SqlSession实例指定Mapper接口,获取相对应的Mapper对象
        UserMapper mapper = sqlSession.getMapper(UserMapper.class);
        // mapper对象调用指定的方法来进行数据库操作
        User user = mapper.selectOne(1010);
        System.out.println("user = " + user);
    }

//    2、接口中有多个零散参数 方式一
    @Test
    public void userAndStart1() {
        SqlSession sqlSession = sqlSessionFactory.openSession(true);
//        通过SqlSession实例指定Mapper接口,获取相对应的Mapper对象
        UserMapper mapper = sqlSession.getMapper(UserMapper.class);
        // mapper对象调用指定的方法来进行数据库操作
        User user = mapper.userAndStart1("jerry", "1");
        System.out.println("user = " + user);
    }

//    2、接口中有多个零散参数 方式二
    @Test
    public void userAndStart2() {
        SqlSession sqlSession = sqlSessionFactory.openSession(true);
//        通过SqlSession实例指定Mapper接口,获取相对应的Mapper对象
        UserMapper mapper = sqlSession.getMapper(UserMapper.class);
        // mapper对象调用指定的方法来进行数据库操作
        User user = mapper.userAndStart2("jerry", "1");
        System.out.println("user = " + user);
    }

//    3、将多个参数封装成实体类对象最为接口参数
    @Test
    public void selectUser() {
        SqlSession sqlSession = sqlSessionFactory.openSession(true);
//        通过SqlSession实例指定Mapper接口,获取相对应的Mapper对象
        UserMapper mapper = sqlSession.getMapper(UserMapper.class);
        User user = new User();
        user.setUser("jerry");
        user.setStart("1");
        // mapper对象调用指定的方法来进行数据库操作
        User user1 = mapper.selectUser(user);
        System.out.println("user1 = " + user1);
    }

//    4、将多个参数保存到Map集合中作为接口参数
    @Test
    public void selectMap() {
        SqlSession sqlSession = sqlSessionFactory.openSession(true);
//        通过SqlSession实例指定Mapper接口,获取相对应的Mapper对象
        UserMapper mapper = sqlSession.getMapper(UserMapper.class);
        Map<String, String> map = new HashMap<>();
        map.put("user","jerry");
        map.put("start","1");
        // mapper对象调用指定的方法来进行数据库操作
        User user = mapper.selectMap(map);
        System.out.println("user = " + user);
    }

Mpper自定义映射

MyBatis优点体现:

        MyBatis提供映射标签,支持对象与数据库字段的ORM映射;提供对象关系映射标签,支持对象关系组件维护。

自定义映射用于数据库字段和实体类属性名不一致的情况,那么遇到该情况如何解决

1、使用SQL语句的别名功能,在查询的SQL语句中定义字段的别名,将数据库字段的别名定义为实体类的属性名。

2、通过MyBatis的映射标签,将数据库的字段名和实体类的属性名 一 一对应

1、创建表

emp员工表

Create Table

CREATE TABLE `emp` (
  `eid` int(11) NOT NULL AUTO_INCREMENT COMMENT '员工编号',
  `ename` varchar(20) NOT NULL COMMENT '员工姓名',
  `age` varchar(10) NOT NULL COMMENT '员工年龄',
  `deptno` varchar(10) NOT NULL COMMENT '部门编号',
  PRIMARY KEY (`eid`)
) ;
package cn.wzw.my.entity;

import lombok.Data;

@Data
public class Emp {

  private long eid;
  private String ename;
  private String age;
  private String deptno;
  // 额外添加的部门属性,用于存储员工对应的部门信息
  private Dept dept;

}

dept部门表

Create Table

CREATE TABLE `dept` (
  `did` int(11) NOT NULL AUTO_INCREMENT COMMENT '部门编号',
  `deptName` varchar(20) NOT NULL COMMENT '部门名称',
  `local` varchar(50) NOT NULL COMMENT '部门地区',
  PRIMARY KEY (`did`)
);
package cn.wzw.my.entity;

import lombok.Data;

@Data
public class Dept {

  private long did;
  private String deptName;
  private String local;
  // 额外添加的员工属性,用于存储对应部门中的所有员工信息
  private List<Emp> emps;

}

2、MyBatis对象之间的关联关系

一对一的关联关系

emp员工表:一个员工只有一个部门;查询出所有员工对应的部门信息

1、EmpMapper接口

package cn.wzw.my.mapper;

import cn.wzw.my.entity.Emp;

import java.util.List;

public interface EmpMapper {
//    查询出所有员工对应的部门信息
    List<Emp> selectAll01();
    List<Emp> selectAll02();
    List<Emp> selectAll03();
}

2、EmpMapper.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="cn.wzw.my.mapper.EmpMapper">
<!--    emp员工表:一个员工只有一个部门;关系为一对一查询-->
<!--    数据库字段和实体类对象属性的ORM关系映射-->
    <resultMap id="empMap1" type="emp">
        <id property="eid" column="eid"></id>
        <result property="ename" column="ename"></result>
        <result property="age" column="age"></result>
        <result property="deptno" column="deptno"></result>
        <association property="dept" javaType="dept">
            <id property="did" column="did"></id>
            <result property="deptName" column="deptName"></result>
            <result property="local" column="local"></result>
        </association>
    </resultMap>
    <select id="selectAll01" resultMap="empMap1">
        select a.*,b.* from `emp` a left outer join `dept` b on(a.`deptno`=b.`did`)
    </select>

<!--    autoMapping:设置数据库字段与实体类属性的自动映射-->
    <resultMap id="empMap2" type="emp" autoMapping="true">
        <association property="dept" javaType="dept">
            <id property="did" column="did"></id>
            <result property="deptName" column="deptName"></result>
            <result property="local" column="local"></result>
        </association>
    </resultMap>
    <select id="selectAll02" resultMap="empMap2">
        select a.*,b.* from `emp` a left outer join `dept` b on(a.`deptno`=b.`did`)
    </select>

<!--    分步查询:先查询emp员工表中的数据,然后根据emp表中结果的deptno部门编号去dept部门表中查询数据-->
    <resultMap id="empMap3" type="emp" autoMapping="true">
<!--        -->
        <association property="dept" javaType="dept" column="deptno" select="deptAll" fetchType="lazy">
            <id property="did" column="did"></id>
            <result property="deptName" column="deptName"></result>
            <result property="local" column="local"></result>
        </association>
    </resultMap>
    <select id="selectAll03" resultMap="empMap3">
        select * from `emp`
    </select>
    <select id="deptAll" resultType="dept">
        select * from `dept` where `did`=#{deptno}
    </select>
</mapper>

3、EmpMapperTest测试类

package cn.wzw.my.mapper;

import cn.wzw.my.entity.Emp;
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.Before;
import org.junit.Test;

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

import static org.junit.Assert.*;

public class EmpMapperTest {
    SqlSessionFactory sqlSessionFactory = null;
    @Before
    public void init(){
        try {
            InputStream resource = Resources.getResourceAsStream("config/mybatis-config.xml");
            sqlSessionFactory = new SqlSessionFactoryBuilder().build(resource);
        } catch (IOException e) {
            throw new RuntimeException(e);
        }
    }

    @Test
    public void selectAll01() {
        SqlSession sqlSession = sqlSessionFactory.openSession(true);
        EmpMapper mapper = sqlSession.getMapper(EmpMapper.class);
        List<Emp> emps = mapper.selectAll01();
        for (Emp emp:emps){
            System.out.println("emp = " + emp);
        }
    }

    @Test
    public void selectAll02() {
        SqlSession sqlSession = sqlSessionFactory.openSession(true);
        EmpMapper mapper = sqlSession.getMapper(EmpMapper.class);
        List<Emp> emps = mapper.selectAll02();
        Iterator<Emp> iterator = emps.iterator();
        while (iterator.hasNext()){
            Emp emp = iterator.next();
            System.out.println("emp = " + emp);
        }
    }

    @Test
    public void selectAll03() {
        SqlSession sqlSession = sqlSessionFactory.openSession(true);
        EmpMapper mapper = sqlSession.getMapper(EmpMapper.class);
        List<Emp> emps = mapper.selectAll03();
        Iterator<Emp> iterator = emps.iterator();
        while (iterator.hasNext()){
            Emp emp = iterator.next();
            System.out.println("emp = " + emp);
        }
    }
}

一对多的关联关系

dept部门表:一个部门有多个员工;查询部门中所有员工信息

1、DeptMapper接口

package cn.wzw.my.mapper;

import cn.wzw.my.entity.Dept;

import java.util.List;

public interface DeptMapper {

    // 查询部门中的所有员工信息
    List<Dept> selectAll01();
    List<Dept> selectAll02();
    List<Dept> selectAll03();
}

2、DeptMapper.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="cn.wzw.my.mapper.DeptMapper">

<!--    使用MyBatis的映射将数据库字段和实体类属性一一对应-->
    <resultMap id="deptMap1" type="dept">
        <id property="did" column="did"></id>
        <result property="deptName" column="deptName"></result>
        <result property="local" column="local"></result>
        <collection property="emps" ofType="emp">
            <id property="eid" column="eid"></id>
            <result property="ename" column="ename"></result>
            <result property="age" column="age"></result>
            <result property="deptno" column="deptno"></result>
        </collection>
    </resultMap>
    <select id="selectAll01" resultMap="deptMap1">
        select a.*,b.* from `dept` a left join `emp` b on(a.`did`=b.`deptno`)
    </select>

<!--    autoMapping:开启自动映射-->
    <resultMap id="deptMap2" type="dept" autoMapping="true">
        <collection property="emps" ofType="emp">
            <id property="eid" column="eid"></id>
            <result property="ename" column="ename"></result>
            <result property="age" column="age"></result>
            <result property="deptno" column="deptno"></result>
        </collection>
    </resultMap>
    <select id="selectAll02" resultMap="deptMap2">
        select a.*,b.* from `dept` a left join `emp` b on(a.`did`=b.`deptno`)
    </select>

<!--    分步查询:先查询dept部门表,根据部门表中结果的did部门编号去另外一张emp员工表中查询数据-->
    <resultMap id="deptMap3" type="dept" autoMapping="true">
        <collection property="emps" ofType="emp" column="did" select="selectDept" fetchType="lazy">
            <id property="eid" column="eid"></id>
            <result property="ename" column="ename"></result>
            <result property="age" column="age"></result>
            <result property="deptno" column="deptno"></result>
        </collection>
    </resultMap>
    <select id="selectAll03" resultMap="deptMap3">
        select * from  `dept`
    </select>
    <select id="selectDept" resultType="dept">
        select * from  `emp` where `deptno`=#{did}
    </select>
</mapper>

3、DeptMapperTest测试类

package cn.wzw.my.mapper;

import cn.wzw.my.entity.Dept;
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.Before;
import org.junit.Test;

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

import static org.junit.Assert.*;

public class DeptMapperTest {
    SqlSessionFactory sqlSessionFactory = null;
    @Before
    public void init(){
        try {
            InputStream resource = Resources.getResourceAsStream("config/mybatis-config.xml");
            sqlSessionFactory = new SqlSessionFactoryBuilder().build(resource);
        } catch (IOException e) {
            throw new RuntimeException(e);
        }
    }

    @Test
    public void selectAll01() {
        SqlSession sqlSession = sqlSessionFactory.openSession(true);
        DeptMapper mapper = sqlSession.getMapper(DeptMapper.class);
        List<Dept> depts = mapper.selectAll01();
//        使用迭代器遍历集合
        Iterator<Dept> iterator = depts.iterator();
        while (iterator.hasNext()){
            Dept dept = iterator.next();
            System.out.println("dept = " + dept);
        }
    }

    @Test
    public void selectAll02() {
        SqlSession sqlSession = sqlSessionFactory.openSession(true);
        DeptMapper mapper = sqlSession.getMapper(DeptMapper.class);
        List<Dept> depts = mapper.selectAll02();
        Iterator<Dept> iterator = depts.iterator();
        while (iterator.hasNext()){
            Dept dept = iterator.next();
            System.out.println("dept = " + dept);
        }
    }

    @Test
    public void selectAll03() {
        SqlSession sqlSession = sqlSessionFactory.openSession(true);
        DeptMapper mapper = sqlSession.getMapper(DeptMapper.class);
        List<Dept> depts = mapper.selectAll03();
        Iterator<Dept> iterator = depts.iterator();
        while (iterator.hasNext()){
            Dept dept = iterator.next();
            System.out.println("dept = " + dept);
        }
    }
}

MyBatis动态SQL

MyBatis的优点体现:

        MyBatis基于SQL语句编程,相当灵活;不会对应用程序或数据库现有的设计造成任何影响;SQL写在XML文件中,解除程序于代码的耦合,方便统一管理;提供XML标签,支持编写动态SQL语句,并可以重用。

动态查询SQL

1、UserMapper接口

/**
     * 第四部分:动态SQL
     * 动态查询
     * 动态修改
     * 动态删除
     */
    /**
     * 动态SQL:
     *      1、<where> + <if>
     *      2、<trim> + <if>
     *      3、<where> + <choose> + <when> + <otherwise>
     */
    // 1、<where> + <if>
    List<User> userAndStart01(User user);
    // 2、<trim> + <if>
    List<User> userAndStart02(User user);
    // 3、<where> + <choose> + <when> + <otherwise>
    List<User> userAndStart03(User user);

2、UserMapper.xml文件

<!--
    /**
     * 第四部分:动态SQL
     * 动态查询
     * 动态修改
     * 动态删除
     */
    /**
     * 动态SQL:
     *      1、<where> + <if>
     *      2、<trim> + <if>
     *      3、<where> + <choose> + <when> + <otherwise>
     */
-->
<!--
    1、<where> + <if>
   <if>:用于判断传入的值是否符合条件。符合条件时执行<if>中的内容,否则不执行
    <where>:where标签会知道如果它包含的标签中有返回值的话,它就插入一个where。此外,如果标签返回的内容是以AND 或OR 开头的,则它会剔除掉
-->
    <select id="userAndStart01" resultType="user">
        select * from `user`
            <where>
                <if test="user!=null">
                    `user`=#{user}
                </if>
                <if test="start!=null">
                    and `start`=#{start}
                </if>
            </where>
    </select>

<!--
    2、<trim> + <if>
    <trim>属性有如下:
        prefix:添加前缀
        prefixOverrides:去除前缀
        suffix:添加后缀
        suffixOverrides:去除后缀
   <trim>:添加前缀where,当第一个if不执行时,在执行第二个<if>时去除前缀and,保证SQL正常查询
   <if>:用于判断传入的值是否符合条件。符合条件时执行<if>中的内容,否则不执行
-->
    <select id="userAndStart02" resultType="user">
        select * from `user`
            <trim prefix="where" prefixOverrides="and">
                <if test="user!=null">
                    `user`=#{user}
                </if>
                <if test="start!=null">
                    and `start`=#{start}
                </if>
            </trim>
    </select>

<!--
    3、<where> + <choose> + <when> + <otherwise>
    <where>:where标签会知道如果它包含的标签中有返回值的话,它就插入一个where。此外,如果标签返回的内容是以AND 或OR 开头的,则它会剔除掉
    <choose> + <when> + <otherwise>:<choose>中的内容从上到下执行,
            如果第一个<when>满足条件,则只执行当前<when>中的内容,不在往下执行;
            如果第一个<when>不满足条件,则执行下一个<when>中的内容,不在往下执行;
            如果第一个<when>都不满足条件,则<otherwise>中的内容;
-->
    <select id="userAndStart03" resultType="user">
        select * from `user`
            <where>
                <choose>
                    <when test="user!=null">
                        `user`=#{user}
                    </when>
                    <when test="start!=null">
                        `start`=#{start}
                    </when>
                    <otherwise></otherwise>
                </choose>
            </where>
    </select>

3、UserMapperTest测试类

/**
     * 第四部分:动态SQL
     * 动态查询
     * 动态修改
     * 动态删除
     */
    /**
     * 动态SQL:
     *      1、<where> + <if>
     *      2、<trim> + <if>
     *      3、<where> + <choose> + <when> + <otherwise>
     */
//    1、<where> + <if>
    @Test
    public void userAndStart01() {
        SqlSession sqlSession = sqlSessionFactory.openSession(true);
        UserMapper mapper = sqlSession.getMapper(UserMapper.class);
        User user = new User();
        user.setUser("tom");
        user.setStart("0");
        List<User> users = mapper.userAndStart01(user);
        Iterator<User> iterator = users.iterator();
        while (iterator.hasNext()){
            User user1 = iterator.next();
            System.out.println("user1 = " + user1);
        }
    }

//    2、<trim> + <if>
    @Test
    public void userAndStart02() {
        SqlSession sqlSession = sqlSessionFactory.openSession(true);
        UserMapper mapper = sqlSession.getMapper(UserMapper.class);
        User user = new User();
        user.setUser("tom");
        user.setStart("0");
        List<User> users = mapper.userAndStart02(user);
        Iterator<User> iterator = users.iterator();
        while (iterator.hasNext()){
            User next = iterator.next();
            System.out.println("next = " + next);
        }
    }

//    3、<where> + <choose> + <when> + <otherwise>
    @Test
    public void userAndStart03() {
        SqlSession sqlSession = sqlSessionFactory.openSession(true);
        UserMapper mapper = sqlSession.getMapper(UserMapper.class);
        User user = new User();
        user.setUser("tom");
        user.setStart("0");
        List<User> users = mapper.userAndStart03(user);
        Iterator<User> iterator = users.iterator();
        while (iterator.hasNext()){
            User next = iterator.next();
            System.out.println("next = " + next);
        }
    }

动态修改SQL

1、UserMapper接口

/**
     * 动态修改SQL:
     *      1、<set> + <if>
     *      2、<trim> + <if>
     */
//    1、<set> + <if>
    Integer updateUser01(User user);
//    2、<trim> + <i
    Integer updateUser02(User user);

2、UserMapper.xml文件

<!--
    /**
     * 动态修改SQL:
     *      1、<set> + <if>
     *      2、<trim> + <if>
     */
-->
<!--
    1、<set> + <if>
    <set>:<set>标签会知道如果它包含的标签中有返回值的话,它就插入一个<set>。此外,如果标签返回的内容是以','开头的,则它会剔除掉
    <if>:用于判断传入的值是否符合条件。符合条件时执行<if>中的内容,否则不执行
-->
    <update id="updateUser01">
        update `user`
        <set>
            <if test="user!=null">
                `user`=#{user}
            </if>
            <if test="password!=null">
                ,`password`=#{password}
            </if>
            <if test="start!=null">
                , `start`=#{start}
            </if>
        </set>
        where `uid`=#{uid}
    </update>

<!--
    2、<trim> + <if>
    <trim>:在执行SQL语句时prefix属性添加前缀<set>,如果标签返回的内容是以','开头的,<trim>会通过prefixOverrides属性去除前缀","
    <if>:用于判断传入的值是否符合条件。符合条件时执行<if>中的内容,否则不执行
-->
    <update id="updateUser02">
        update `user`
        <trim prefix="set" prefixOverrides=",">
            <if test="user!=null">
                `user`=#{user}
            </if>
            <if test="password!=null">
                ,`password`=#{password}
            </if>
            <if test="start!=null">
                , `start`=#{start}
            </if>
        </trim>
        where `uid`=#{uid}
    </update>

3、UserMapperTest测试类

    /**
     * 动态修改SQL:
     *      1、<set> + <if>
     *      2、<trim> + <if>
     */
    @Test
    public void updateUser01() {
        SqlSession sqlSession = sqlSessionFactory.openSession(true);
        UserMapper mapper = sqlSession.getMapper(UserMapper.class);
        User user = new User();
        user.setUid(1010);
//        user.setUser("jerry");
        user.setPassword("1008611");
//        user.setStart("0");
        Integer result = mapper.updateUser01(user);
        System.out.println(result!=0?"修改成功":"修改失败");
    }

    @Test
    public void updateUser02() {
        SqlSession sqlSession = sqlSessionFactory.openSession(true);
        UserMapper mapper = sqlSession.getMapper(UserMapper.class);
        User user = new User();
        user.setUid(1010);
//        user.setUser("jerry");
        user.setPassword("123456");
        user.setStart("1");
        Integer result = mapper.updateUser02(user);
        System.out.println(result!=0?"修改成功":"修改失败");
    }

动态删除SQL

1、UserMappe接口

   /**
     * 动态删除
     *      1、where + foreach
     *      2、trim + foreach
     */
//    1、where + foreach
    Integer deleteUser01(List list);
//    2、trim + foreach
    Integer deleteUser02(List list);

2、UserMapper.xml文件

<!--    
    /**
     * 动态删除
     *      1、where + foreach
     *      2、trim + foreach
     */
-->
<!--
    1、where + foreach
-->
    <delete id="deleteUser01">
        delete from `user`
            <where>
                <!--
                    collection:指定输入对象中的集合属性
                    item:每次遍历生成的对象
                    open:开始遍历时的拼接字符串
                    close:结束时拼接的字符串
                    separator:遍历对象之间需要拼接的字符串
                    删除形式:delete  from `user` where `uid`=1 or `uid`=2 or `uid`=3
                -->
                <foreach collection="list" item="uid" separator="or">
                    `uid`=#{uid}
                </foreach>
            </where>
    </delete>

<!--
    2、trim + foreach
-->
    <delete id="deleteUser02">
        delete from `user`
        <where>
            <!--
                collection:指定输入对象中的集合属性
                item:每次遍历生成的对象
                open:开始遍历时的拼接字符串
                close:结束时拼接的字符串
                separator:遍历对象之间需要拼接的字符串
                删除形式:delete  from `user` where `uid` in(id=1 or id=2 or id=3)
            -->
            <foreach collection="list" item="uid" open="`uid` in(" separator="," close=")">
                #{uid}
            </foreach>
        </where>
    </delete>

3、UserMapperTest测试类

    /**
     * 动态删除
     *      1、where + foreach
     *      2、trim + foreach
     */
//    1、where + foreach
//    删除形式:delete  from `user` where `uid`=1 or `uid`=2 or `uid`=3
    @Test
    public void deleteUser01() {
        SqlSession sqlSession = sqlSessionFactory.openSession(true);
        UserMapper mapper = sqlSession.getMapper(UserMapper.class);
        Integer result = mapper.deleteUser01(Arrays.asList(1009, 1010));
        System.out.println(result!=0?"删除成功":"删除失败");
    }

//    2、trim + foreach
//    删除形式:delete  from `user` where `uid` in(id=1 or id=2 or id=3)
    @Test
    public void deleteUser02() {
        SqlSession sqlSession = sqlSessionFactory.openSession(true);
        UserMapper mapper = sqlSession.getMapper(UserMapper.class);
        Integer result = mapper.deleteUser02(Arrays.asList(1009, 1010));
        System.out.println(result!=0?"删除成功":"删除失败");
    }

MyBatis注解开发

MyBatis可以通过XML或注解的方式来配置和映射原生信息,将POJO映射成数据库中的记录,几乎避免了所有的JDBC代码和手动设置参数,以及获取结果集。

MyBatis的注解开发可直接在接口中指定的接口方法上通过注解的方式书写SQL语句,避免在xml配置文件中书写SQL语句。

1、UserMapper接口

    /**
     * 第五部分:使用注解开发实现增删改查操作
     */
//    增加
    @Insert("insert into `user` (`user`,`password`,`start`) values (#{user},#{password},#{start})")
    Integer userInsert(User user);

//    修改
    @Update("update `user` set `user`=#{user},`password`=#{password},`start`=#{start} where `uid`=#{uid}")
    Integer userUpdate(User user);

//    删除
    @Delete("delete from `user` where `uid`=#{uid}")
    Integer userDelete(Integer uid);

//    查询单条记录
    @Select("select * from `user` where `uid`=#{uid}")
    User userSelectById(Integer uid);

//    查询所有记录
    @Select("select * from `user`")
    List<User> userSelectAll();

2、UserMapperTest测试类

    /**
     * 第五部分:使用注解开发实现增删改查操作
     */
//    增加
    @Test
    public void userInsert() {
        SqlSession sqlSession = sqlSessionFactory.openSession(true);
        UserMapper mapper = sqlSession.getMapper(UserMapper.class);
        User user = new User();
        user.setUser("lisi");
        user.setPassword("123456");
        user.setStart("1");
        Integer result = mapper.userInsert(user);
        System.out.println(result!=0?"添加成功":"添加失败");
    }

//    修改
    @Test
    public void userUpdate() {
        SqlSession sqlSession = sqlSessionFactory.openSession(true);
        UserMapper mapper = sqlSession.getMapper(UserMapper.class);
        User user = new User();
        user.setUid(1011);
        user.setUser("lucky");
        user.setPassword("954321");
        user.setStart("0");
        Integer result = mapper.userUpdate(user);
        System.out.println(result!=0?"修改成功":"修改失败");
    }

//    删除
    @Test
    public void userDelete() {
        SqlSession sqlSession = sqlSessionFactory.openSession(true);
        UserMapper mapper = sqlSession.getMapper(UserMapper.class);
        Integer result = mapper.userDelete(1011);
        System.out.println(result!=0?"删除成功":"删除失败");
    }

//    查询单条记录
    @Test
    public void userSelectById() {
        SqlSession sqlSession = sqlSessionFactory.openSession(true);
        UserMapper mapper = sqlSession.getMapper(UserMapper.class);
        User user = mapper.userSelectById(1010);
        System.out.println("user = " + user);
    }

//    查询所有记录
    @Test
    public void userSelectAll() {
        SqlSession sqlSession = sqlSessionFactory.openSession(true);
        UserMapper mapper = sqlSession.getMapper(UserMapper.class);
        List<User> users = mapper.userSelectAll();
        Iterator<User> iterator = users.iterator();
        while (iterator.hasNext()){
            User user = iterator.next();
            System.out.println("user = " + user);
        }
    }

MyBatis缓存机制

        MyBatis的缓存分为一级缓存和二级缓存,一级缓存是SqlSession级别的缓存,二级缓存是Mapper级别的缓存,二级缓存是多个SqlSession共享的。MyBatis通过缓存机制减轻数据压力,提高数据库性能。

一级缓存:

        MyBatis的一级缓存是SqlSession级别的缓存,在操作数据库时需要构造SqlSession对象,在对象中有一个HashMap用于存储缓存数据,不同的SqlSession之间缓存数据区域是相互不影响的。

        一级缓存的作用域是SqlSession范围的,当在同一个SqlSession中执行两次相同的sql语句时,第一次执行完毕会将数据库中查询的数据写到缓存中,第二次查询时会从缓存中获取数据,不再去底层进行数据库查询,从而提高了查询效率。需要注意的是:如果SqlSession执行了增加、修改、删除操作,MyBatis则会清空SqlSession中的一级缓存,这样做的目的是为了保证缓存数据中存储的最新信息,避免出现脏读现象。

        当一个SqlSession结束后该SqlSession中的一级缓存也就不存在了,MyBatis默认开启一级缓存,不需要进行任何配置。

注意:MyBatis的缓存机制是基于id进行缓存,也就是说MyBatis在使用HashMap缓存机制,是使用对象id作为key,而对象作为value保存。

二级缓存:

        二级缓存是Mapper级别的缓存机制,使用二级缓存时,多个SqlSession使用同一个Mapper的sql语句去操作数据库,得到的数据会存在二级缓存区域,它同样是使用HashMapper进行数据存储,相比一级缓存SqlSession,二级缓存的范围更大,多个SqlSession可以公用二级缓存,二级缓存是跨SqlSession的。

        二级缓存是多个SqlSession共享的,其作用域是Mapper的同一个namespace,不同的SqlSession两次执行相同的Mapper下的sql语句,且向sql中传递的参数也相同,即最终执行相同的sql语句,则第一次执行完毕会将数据库中查询的数据写到缓存,第二次查询时会从缓存中获取数据,不再去底层数据库查询,从而提高查询效率。

        MyBatid默认没有开启二级缓存,需要再手动开启二级缓存。

MyBatis二级缓存

一级缓存:MyBatis默认开启一级缓存。

一级缓存失效情况:

1.不同的SqlSession对应不同的缓存

2.同一个SqlSession但是查询条件不同

3.同一个SqlSession执行两次相同查询之间做了增删改的操作

4.同一个SqlSession执行两次相同查询之间手动清空缓存

二级缓存:MyBatis默认没有开启二级缓存,需要手动开启二级缓存。

二级缓存失效的条件:
在两次查询之间进行了任意的增删改操作,一级二级缓存同时失效

开启二级缓存:

  1. 第一步:在配置文件中开启二级缓存
  2. 第二步:在对应的xml映射文件中开启二级缓存
  3. 第三步:查询数据封装的实体类要实现序列化接口
  4. 第四步:二级缓存需要在一级缓存失效或提交后生效

第一步:mybatis-config.xml配置文件

<!--        第一步:在配置文件中开启二级缓存-->
        <setting name="cacheEnabled" value="true"/>
<?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 resource="config/jdbc.properties"></properties>
    <settings>
<!--        开启驼峰命名-->
        <setting name="mapUnderscoreToCamelCase" value="true"/>
<!--        开启日志-->
        <setting name="logImpl" value="log4j"/>
<!--        第一步:在配置文件中开启二级缓存-->
        <setting name="cacheEnabled" value="true"/>
    </settings>
<!--    设置别名-->
    <typeAliases>
        <package name="cn.wzw.my.entity"/>
    </typeAliases>
    <environments default="development">
        <environment id="development">
<!--            事务管理-->
            <transactionManager type="JDBC"/>
<!--            配置数据源-->
            <dataSource type="POOLED">
<!--                使用配置文件中的键,设置数据库驱动、链接地址、用户名、密码-->
                <property name="driver" value="${jdbc.driver}"/>
                <property name="url" value="${jdbc.url}"/>
                <property name="username" value="${jdbc.user}"/>
                <property name="password" value="${jdbc.password}"/>
            </dataSource>
        </environment>
    </environments>
<!--    mapper接口映射-->
    <mappers>
        <package name="cn.wzw.my.mapper"/>
    </mappers>
</configuration>

第二步:在UserMapper.xml映射文件中开启二级缓存

<!--
    /**
     * 第六部分:MyBatis二级缓存
     */
-->
    <!--    第二步:在对应的xml映射文件中开启二级缓存    -->
    <cache></cache>
<!--    验证MyBatis缓存机制的查询语句-->
    <select id="selectOneUser" resultType="user">
        select * from `user` where `uid`=#{uid}
    </select>

第三步:User实体类要实现序列化接口

package cn.wzw.my.entity;

import lombok.Data;

import java.io.Serializable;
import java.util.List;

//   第三步:查询数据封装的实体类要实现序列化接口
@Data
public class User implements Serializable {

  private long uid;
  private String user;
  private String password;
  private String start;
  // 额外添加的员工属性,用于存储对应部门中的所有员工信息
  private List<Emp> emps;
}

 第四步:二级缓存需要在一级缓存失效或提交后生效

UserMapper.xml文件

    /**
     * 第六部分:MyBatis二级缓存
     */
    User selectOneUser(Integer uid);

UserMapperTest测试类

    /**
     * 第六部分:MyBatis二级缓存
     */
    @Test
    public void selectOneUser() {
        SqlSession sqlSession = sqlSessionFactory.openSession(true);
        UserMapper mapper = sqlSession.getMapper(UserMapper.class);
        User user = mapper.selectOneUser(1010);
        System.out.println("user = " + user);

//        第四步:二级缓存需要在一级缓存失效或提交后生效
//        清空一级缓存
        sqlSession.commit();

        UserMapper mapper1 = sqlSession.getMapper(UserMapper.class);
        User user1 = mapper1.selectOneUser(1010);
        System.out.println("user1 = " + user1);
    }

MyBatis分页插件

第一步:pom.xml 中添加分页插件依赖

<!--        分页依赖-->
        <dependency>
            <groupId>com.github.pagehelper</groupId>
            <artifactId>pagehelper</artifactId>
            <version>5.3.0</version>
        </dependency>

第二步:mybatis-config.xml配置文件中配置分页插件

复制pagehelper分页插件中的PageInterceptor文件路径

    <plugins>
<!--        
pagehelper分页插件中的PageHelper文件路径:"com.github.pagehelper.PageInterceptor"-->
        <plugin interceptor="com.github.pagehelper.PageInterceptor"></plugin>
    </plugins>
<?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 resource="config/jdbc.properties"></properties>
    <settings>
<!--        开启驼峰命名-->
        <setting name="mapUnderscoreToCamelCase" value="true"/>
<!--        开启日志-->
        <setting name="logImpl" value="log4j"/>
<!--        第一步:在配置文件中开启二级缓存-->
        <setting name="cacheEnabled" value="true"/>
    </settings>
<!--    设置别名-->
    <typeAliases>
        <package name="cn.wzw.my.entity"/>
    </typeAliases>
<!--    配置分页插件-->
    <plugins>
<!--        pagehelper分页插件中的PageHelper文件路径:"com.github.pagehelper.PageHelper"-->
        <plugin interceptor="com.github.pagehelper.PageHelper"></plugin>
    </plugins>
    <environments default="development">
        <environment id="development">
<!--            事务管理-->
            <transactionManager type="JDBC"/>
<!--            配置数据源-->
            <dataSource type="POOLED">
<!--                使用配置文件中的键,设置数据库驱动、链接地址、用户名、密码-->
                <property name="driver" value="${jdbc.driver}"/>
                <property name="url" value="${jdbc.url}"/>
                <property name="username" value="${jdbc.user}"/>
                <property name="password" value="${jdbc.password}"/>
            </dataSource>
        </environment>
    </environments>
<!--    mapper接口映射-->
    <mappers>
        <package name="cn.wzw.my.mapper"/>
    </mappers>
</configuration>

第三步:UserMapperTest测试类中查询数据测试分页插件PageHelper

    /**
     * 第七部分:MuBatis分页插件PageHelper
     */
    @Test
    public void pageHelper(){
        SqlSession sqlSession = sqlSessionFactory.openSession(true);
        UserMapper mapper = sqlSession.getMapper(UserMapper.class);
//        使用分页插件进行分页显示;pageNum:表现页数;pageSize:表示每页显示多少条记录
        PageHelper.startPage(1,3);
//        查询所有数据
        List<User> users = mapper.selectUserAll();
//        iterator迭代器遍历集合
        Iterator<User> iterator = users.iterator();
        while (iterator.hasNext()){
            User user = iterator.next();
            System.out.println("user = " + user);
        }

        PageInfo<User> pageInfo = new PageInfo<>(users);
        //获取分页的相关数据
        System.out.println(pageInfo);
        //获取数据记录总条数
        long total = pageInfo.getTotal();
        System.out.println(total);
        //获取当前页的显示数据记录
        List<User> list = pageInfo.getList();
        for (User user:list){
            System.out.println("user = " + user);
        }
    }
  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值