MyBatis全方位整理,内附源代码

MyBatis

1.概述

主流的ORM框架,之前叫做iBatis,后更名为MyBatis(ORM还有一个主流的框架,Hibernate)

  • 二者区别

  • MyBatis:半自动ORM框架

    框架值提供一部分功能,剩下的要我们手动完成即MyBatis没有提供pojo与数据库表的映射,它只是实现了pojo和SQL之间的映射关系,需要开发者自定义SQL语句,以及数据与pojo之间的装配关系

  • Hibernate:全自动框架

    实现类pojo和数据库之间的映射,同时可以自动生成SQL语句,并完成执行

MyBatis虽然没有Hibernate方便,但是这种半自动化的方式提高了框架的灵活性,开发者可以根据具体的业务需求,完成定制化的持久层解决方案

MyBatis是一款优秀的持久框架,它支持自定义sql,存储过程及高级映射,MyBatis简化了几乎所有的JDBC代码,以及设置参数,获取结果集对象的工作。MyBatis可以通过简单的XML配置或注解来配置映射关系。

复习JDBC

//1.注册驱动
Class.forName("com.mysql.jdbc.Driver");
//2.获取连接
Connection connection = Drivermanager.getConnection(url,username,password); 
//3.定义sql
String sql = "select * from student where id = ?";
//4.预编译
PreparedStatement statement = connection.preparedStatement(sql);
//5.设置参数
statement.setInteger(1,2001);
//6. 执行sql,封装结果
ResultSet result = statement.executeQuery();

**Hibernate框架:**全自动映射ORM框架

2.为什么使用MyBatis

​ JDBC:

SQL编写在代码中,耦合度比较高

实际开发中SQL会经常被更新,维护不易

​ Hibernate:

内部自动生成SQL,不方便特殊优化

长难复杂的SQL,对Hibernate处理很不容易

基于全映射的全自动框架,进行字段部分映射比较困难,并且会导致数据库性能下降

MyBatis:

SQL和Java编码分离功能划分清楚,一个专注数据,一个专注业务

核心SQL可以自己编写,优化比较方便

3.MyBatis环境搭建

步骤:

1.创建Maven工程,并导入相关依赖

2.创建实体类

3.创建dao层接口

4.创建MyBatis主配置文件:SQLMapConfig.xml

5.创建映射配置文件UseDao.xml

注意事项:

1.创建Directory和packge的区别

directory:com.wdzl.dao创建的是以及目录

packge:com.wdzl.dao创建了三级目录

2.MyBatis的映射配置文件所在目录层级要与对应的dao层接口目录层级相同

3.映射配置文件mapper标签namespace属性的值必须对应接口的全限定类名

4.映射配置文件selet标签id属性必须与对应接口中的方法名一直,不能随便写

5.只要遵循2,3,4,的规定,我们就不用去写接口的实现类

3.2测试案例

步骤:

1.读取配置文件

2.创建Sqlsessionfactory 对象–>通过SqlSessionFactoryBuilder对象获取

创建工厂使用构建者模式

构建者模式:把复杂的对象构建细节进行隐藏,使得使用者直接调用方法拿到该对象

3.使用工厂对象生产SqlSession对象

生产SqlSession使用了工厂模式

工厂模式:

a.解耦:降低类与类之间的耦合性,因为屏蔽了new关键字

b.便于维护:将对象的创建和使用进行分离,当业务逻辑发生变化时,只需要修改工厂中的代码即可

4.使用SQLSession对象获取接口代理对象

代理模式:不改变源码的情况下对已有的方法进行增强

5.使用代理对象调用方法

6.释放资源

a.入门案例

现在是最复杂的状态,后面学了注解等方法后就不一样了

在pom文件里导入依赖

    <dependencies>
        <!--测试单元-->
        <dependency>
            <groupId>junit</groupId>
            <artifactId>junit</artifactId>
            <version>4.12</version>
            <scope>test</scope>
        </dependency>
        <dependency>
            <!--MySql连接驱动-->
            <groupId>mysql</groupId>
            <artifactId>mysql-connector-java</artifactId>
            <version>5.1.6</version>
        </dependency>
        <dependency>
            <!--MyBatis-->
            <groupId>org.mybatis</groupId>
            <artifactId>mybatis</artifactId>
            <version>3.5.6</version>
        </dependency>
        <dependency>
            <!--日志解析lo4j-->
            <groupId>log4j</groupId>
            <artifactId>log4j</artifactId>
            <version>1.2.17</version>
        </dependency>
    </dependencies>

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-0d6DHO8X-1616916840107)(C:\Users\dell\Pictures\java截图\HelloMyBatis结构截图.png)]

以上是结构截图

  • 现在UserDao 里面创建一个List作为入门案例
public interface UserDao {
    
    
    /**
     * 查询所有用户信息
     */

    List<Student> findAll();
}
  • 再在pojo里根据数据库表创建一个实体类,这里我直接用我的表,但是无参,有参,get,set,toString 我就不写了
/**
 * 学生类
 */
public class Student {
    
    
    private int id;
    private String username;
    private String gender;
    private String birthday;
    private String address;
}
  • 在resource里面,创建两个数据库的配置文件 的配置文件UserDao.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.wdzl.dao.UserDao"><!--对应dao层接口的权限定类名-->
    <select id="findAll" resultType="com.wdzl.pojo.Student">
        select  * from student;
    </select>
</mapper>
  • SqlMapConfig.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="mysql">
        <environment id="mysql">
            <!--配置事务的类型-->
            <transactionManager type="JDBC"></transactionManager>
            <!--配置数据源-->
            <dataSource type="POOLED">
                <!--配置连接数据库的4个基本信息-->
                <property name="driver" value="com.mysql.jdbc.Driver"/>
                <property name="url" value="jdbc:mysql://localhost:3306/mybatis"/>
                <property name="username" value="root"/>
                <property name="password" value="root"/>
            </dataSource>
        </environment>
    </environments>
    <mappers>
        <mapper resource="com/wdzl/dao/UserDao.xml"/>
    </mappers>
</configuration>
  • test
/**
 * UserDao测试类
 * @author lp
 * @version 1.0
 * MyBatis 入门案例测试实现步骤
 *     1.读取配置文件
 *     2.创建SqlSessionFactory工厂
 *     3.用工厂生产SqlSession对象
 *     4.使用SqlSessiond对象创建dao层的带对象
 *     5.使用代理对象执行方法
 *     6.释放资源
 */
public class UserDaoTest {
    
    
    @Test
    public void findAllTest() throws IOException {
    
    
        //读取配置文件
        InputStream is = Resources.getResourceAsStream("sqlMapConfig.xml");
        //2.创建SqlSessionFactory工厂
        SqlSessionFactoryBuilder builder = new SqlSessionFactoryBuilder();
        SqlSessionFactory factory = builder.build(is);
        //3.用工厂生产SqlSession对象
        SqlSession session = factory.openSession();
        //4.使用SqlSessiond对象创建dao层的带对象
        UserDao userDao = session.getMapper(UserDao.class);
        //5.使用代理对象执行方法
        List<Student> students = userDao.findAll();
        //遍历
        for (Student student:students){
    
    
            System.out.println(student);
        }
        //释放资源
        session.close();
        is.close();
    }
}

b.入门案例2.0(添加注解)

该案例只是对上面的进行简单的修改

  • 首先将xml文件中的标签进行修改,resource->classs&&/->.&&userDao.xml->userDao其中UserDao.xml已经删除(注解会将其替代)
   <mappers>
        <mapper class="com.wdzl.dao.UserDao"/>
    </mappers>
  • 在UserDao上直接注解
public interface UserDao {
    
    
    /**
     * 查询所有用户信息
     */
    @Select("select  * from student;")
    List<Student> findAll();
}
  • 实体类不变

  • test不变

效果与之前相同

c.关于myBatis的增删改查(crud)(xml方法)

1.在UserDao接口里创建每个需求的接口

public interface UserDao {
    
    
    /**
     * 查询所有用户信息
     */
    List<User> findAll();

    /**
     * 添加用户的方法
     * @param user
     */
    void addUser(User user);

    /**
     * 修改用户信息
     */
    void updateUser(User user);

    /**
     * 删除用户
     */
    void deleteUser(User user);
    }

2.创建User实体类,与数据库表一一对应

get,set,有参无参,toString这些我就不写了

public class User {
    
    
    private int uid;
    private String username;
    private String sex;
    private String birthday;
    private String address;
}

在xml里将这些方法相应的SQL语言都写上(如想完成其他更复杂的操作,只需要类似在xml文件中添加更复杂的SQL语句)

<?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.wdzl.dao.UserDao"><!--对应dao层接口的全限定类名-->
    <resultMap id="userMap" type="com.wdzl.pojo.User">
        <id property="uid" column="id"></id>
            <!--实体类对应-->      <!--数据库对应-->      
        <result property="username" column="username"></result>
    </resultMap>
    <!--查询所有用户信息的方法-->
    <select id="findAll" resultMap="userMap">
       select * from user
    </select>
    <!--添加用户-->
    <insert id="addUser" parameterType="com.wdzl.pojo.User">
          <selectKey keyProperty="uid" order="AFTER" resultType="int">
          select last_insert_id();
          </selectKey>
        insert into user(username,birthday,sex,address) values (#{
    
    username},#{
    
    birthday},#{
    
    sex},#{
    
    address})
    </insert>
    <!--修改信息-->
    <update id="updateUser" parameterType="com.wdzl.pojo.User">
        update user set address=${
    
    address} where username=${
    
    username}
    </update>
    <!--删除用户-->
    <delete id="deleteUser" parameterType="com.wdzl.pojo.User">
        delete from user where username=#{
    
    username}
    </delete>
</mapper>

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="mysql">
        <environment id="mysql">
            <!--配置事务的类型-->
            <transactionManager type="JDBC"></transactionManager>
            <!--配置数据源-->
            <dataSource type="POOLED">
                <!--配置连接数据库的4个基本信息-->
                <property name="driver" value="com.mysql.jdbc.Driver"/>
                <property name="url" value="jdbc:mysql://localhost:3306/mybatis?useUnicode=true&amp;characterEncoding=utf-8"/>
                <property name="username" value="root"/>
                <property name="password" value="200429@wbnb"/>
            </dataSource>
        </environment>
    </environments>

    <mappers>
        <mapper resource="com/wdzl/dao/UserDao.xml"/>
    </mappers>

</configuration>

test

/**
 *  UserDao测试类
 * @author lp
 * @version 1.0
 * MyBatis入门案例测试实现步骤
 *      1. 读取配置文件
 *      2.创建SqlSessionFactory工厂
 *      3.用工厂生产SqlSession对象
 *      4.使用SqlSession对象创建dao层的代理对象
 *      5.使用代理对象执行方法
 *      6.释放资源
 */
public class UserDaoTest {
    
    
    InputStream is;
    SqlSessionFactoryBuilder builder;
    SqlSessionFactory factory;
    SqlSession sqlSession;
    UserDao userDao;
    @Before
    public void init() throws IOException {
    
    
        //1.读取配置文件
        is = Resources.getResourceAsStream("SqlMapConfig.xml");
        //2.创建SqlSessionFactory工厂
        builder = new SqlSessionFactoryBuilder();
        factory = builder.build(is);
        //3.用工厂生产SqlSession对象
        sqlSession = factory.openSession();
        //4.使用SqlSession对象创建dao层的代理对象
       userDao = sqlSession.getMapper(UserDao.class);
    }
    @After
    public void destroy() throws IOException {
    
    
        sqlSession.close();
        is.close();
    }


    @Test
    public void findAllTest() throws IOException {
    
    
        List<User> users = userDao.findAll();
        for (User user :users) {
    
    
            System.out.println(user);
        }
    }
    @Test
    public void testAddUser() throws IOException {
    
    
        User user = new User(0, "**", "男", "2000-01-01", "宝鸡");
        userDao.addUser(user);
        System.out.println(user);
        sqlSession.commit();//提交事务
        System.out.println("--------------------------");
        System.out.println(user);
    }

    @Test
    public void testUpdateUser() {
    
    
        User user = new User();
        user.setUsername("**");
        user.setAddress("西安");
        userDao.updateUser(user);

        //5.使用代理对象执行方法
        List<User> users = userDao.findAll();
        //遍历
        for (User user2 :users) {
    
    
            System.out.println(user2);
        }
    }

    @Test
    public void testDeleteUser() {
    
    
        User user = new User();
        user.setUsername("**");
        userDao.deleteUser(user);

        //5.使用代理对象执行方法
        List<User> users = userDao.findAll();
        //遍历
        for (User user2 :users) {
    
    
            System.out.println(user2);
        }

      }
    }

d.MyBatis多表查询

在MySql中,表与表之间有三种

1.1-1

2.1-多

3.多-多

举例

一对一:公民和身份证号

一对多,多对一:

​ 多个学生对应班级

​ 一个班级有多个学生

多对多:学生和老师

  • 特殊

    如果将订单取出,这个订单只能属于一个用户,索引在MyBatis 里就把多对一的关系,按照一对一的关系纪念性处理

d.1多表查询crud

  1. 导包

        <dependencies>
            <!--测试单元-->
            <dependency>
                <groupId>junit</groupId>
                <artifactId>junit</artifactId>
                <version>4.12</version>
                <scope>test</scope>
            </dependency>
            <!--Mysql连接驱动-->
            <dependency>
                <groupId>mysql</groupId>
                <artifactId>mysql-connector-java</artifactId>
                <version>5.1.6</version>
            </dependency>
            <!--mybatis-->
            <dependency>
                <groupId>org.mybatis</groupId>
                <artifactId>mybatis</artifactId>
                <version>3.5.6</version>
            </dependency>
            <!--日志解析lo4j-->
            <dependency>
                <groupId>log4j</groupId>
                <artifactId>log4j</artifactId>
                <version>1.2.17</version>
            </dependency>
        </dependencies>
    
  2. 建实体类

public class User {
    
    
    private int id;
    private String username;
    private String sex;
    private String birthday;
    private String address;
}
public class QueryVo {
    
    
    private User user;
    private List<Integer> ids;
    public User getUser() {
    
    
        return user;
    }

    public void setUser(User user) {
    
    
        this.user = user;
    }

    public List<Integer> getIds() {
    
    
        return ids;
    }

    public void setIds(List<Integer> ids) {
    
    
        this.ids = ids;
    }
}
public class Account {
    
    
    private int id;
    private int uid;
    private double money;
}

3.创建接口

package com.wdzl.dao;

import com.wdzl.pojo.QueryVo;
import com.wdzl.pojo.User;

import java.util.List;

/**
 *  操作学生数据的接口
 */
public interface UserDao {
    
    
    /**
     * 查询所有用户信息
     */
    List<User> findAll();


    /**
     * 根据id查询指定用户信息
     */
    User findUserById(int id);

    /**
     * 模糊查询-根据用户名模糊查询用户信息
     */
    List<User> findUserByName(String name);

    /**
     * 查询用户总记录数
     */
    int findTotal();
/**
 * 根据给定的条件,对满足条件的用户信息进行符合查询
 * 查询满足名称为周杰伦,性别为男的所有用户信息
 */
List<User> findUserByCondictions(User user);


List<User> findUserByIds(QueryVo vo);

}

4.创建userDao配置文件

<?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.wdzl.dao.UserDao"><!--对应dao层接口的全限定类名-->
    <sql id="userBase">
        select * from user
    </sql>
    <resultMap id="userMap" type="com.wdzl.pojo.User">
        <id property="uid" column="id"></id>
        <result property="username" column="username"></result>
    </resultMap>
    <!--查询所有用户信息的方法-->
    <select id="findAll" resultType="user">
       <include refid="userBase"></include>
    </select>
    <!--模糊查询-->
    <select id="findUserByName" parameterType="string" resultType="com.wdzl.pojo.User">
        select * from user where username like #{
    
    name}
    </select>
    <!--查询用户总记录数-->
    <select id="findTotal" resultType="int">
         select count(id) from user
    </select>
    <!--根据包装类模糊查询用户数据-->
    <select id="findUserByVo" parameterType="com.wdzl.pojo.QueryVo" resultType="com.wdzl.pojo.User">
        select * from user where username like #{
    
    user.username}
    </select>
    <!--根据指定信息进行符合条件查询-->
    <select id="findUserByCondictions" parameterType="user" resultType="user">
        select * from user
       <where>
        <if test="username!=null">
        and username=#{
    
    username}
        </if>
        <if test="sex!=null">
            and sex=#{
    
    sex}
        </if>
       </where>
    </select>
    <select id="findUserByIds" parameterType="queryVo" resultType="user">
        select * from user
        <where>
            <if test="ids!=null and ids.size()>0">
                <foreach collection=" ids" open="and id in(" close=")" item="id" separator=",">
                    #{
    
    id}
                </foreach>
            </if>
        </where>
    </select>
</mapper>

5.创建总配置文件

<?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>
    <typeAliases>
        <!--        <typeAlias type="com.wdzl.pojo.User" alias="aa"></typeAlias>-->
        <package name="com.wdzl.pojo" />
    </typeAliases>
    <!-- 配置环境 -->
    <environments default="mysql">
        <environment id="mysql">
            <!--配置事务的类型-->
            <transactionManager type="JDBC"></transactionManager>
            <!--配置数据源-->
            <dataSource type="POOLED">
                <!--配置连接数据库的4个基本信息-->
                <property name="driver" value="com.mysql.jdbc.Driver"/>
                <property name="url" value="jdbc:mysql://localhost:3306/mybatis?useUnicode=true&amp;characterEncoding=utf-8"/>
                <property name="username" value="root"/>
                <property name="password" value="200429@wbnb"/>
            </dataSource>
        </environment>
    </environments>

    <mappers>
        <mapper resource="com/wdzl/dao/UserDao.xml"/>
    </mappers>

</configuration>

test

package com.wdzl.dao;
import com.wdzl.pojo.QueryVo;
import com.wdzl.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.After;
import org.junit.Before;
import org.junit.Test;

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

/**
 *  UserDao测试类
 * @author lp
 * @version 1.0
 * MyBatis入门案例测试实现步骤
 *      1. 读取配置文件
 *      2.创建SqlSessionFactory工厂
 *      3.用工厂生产SqlSession对象
 *      4.使用SqlSession对象创建dao层的代理对象
 *      5.使用代理对象执行方法
 *      6.释放资源
 */
public class UserDaoTest {
    
    
    InputStream is;
    SqlSessionFactoryBuilder builder;
    SqlSessionFactory factory;
    SqlSession sqlSession;
    UserDao userDao;
    @Before
    public void init() throws IOException {
    
    
        //1.读取配置文件
        is = Resources.getResourceAsStream("SqlMapConfig.xml");
        //2.创建SqlSessionFactory工厂
        builder = new SqlSessionFactoryBuilder();
        factory = builder.build(is);
        //3.用工厂生产SqlSession对象
        sqlSession = factory.openSession();
        //4.使用SqlSession对象创建dao层的代理对象
       userDao = sqlSession.getMapper(UserDao.class);
    }
    @After
    public void destroy() throws IOException {
    
    
        sqlSession.close();
        is.close();
    }


    @Test
    public void findAllTest() throws IOException {
    
    

        //5.使用代理对象执行方法
        List<User> users = userDao.findAll();
        //遍历
        for (User user :users) {
    
    
            System.out.println(user);
        }

    }

    @Test
    public void testFindUserById() {
    
    
        User user = userDao.findUserById(9);
        System.out.println(user);
    }

    @Test
    public void testFindUserByName() {
    
    
        List<User> users = userDao.findUserByName("%德%");
        for (User user :users) {
    
    
            System.out.println(user);
        }
    }

    @Test
    public void testFindTotal() {
    
    
        int total = userDao.findTotal();
        System.out.println(total);
    }
    @Test
    public void testFindUserByConditions(){
    
    
        User user = new User();
        user.setUsername("周杰伦");
        user.setSex("男");
        List<User> users = userDao.findUserByCondictions(user);
        for (User u:users){
    
    
            System.out.println(u);
        }
    }
    @Test
    public void testFindUserByQueryVo(){
    
    
        QueryVo vo = new QueryVo();
        List<Integer> list = new ArrayList<>();
        list.add(1);
        list.add(3);
        list.add(5);
        list.add(7);
        list.add(9);
        vo.setIds(list);
        List<User> users = userDao.findUserByIds(vo);
        for (User u:users){
    
    
            System.out.println(u);
        }
  }
}

d.2多表查询一对一

假设一个账户对应一个用户,一个用户也对应一个账户

  • 导依赖
<?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.wdzl</groupId>
    <artifactId>mybatis_manyToOne</artifactId>
    <version>1.0-SNAPSHOT</version>
    <packaging>jar</packaging>
    <dependencies>
        <!--测试单元-->
        <dependency>
            <groupId>junit</groupId>
            <artifactId>junit</artifactId>
            <version>4.12</version>
            <scope>test</scope>
        </dependency>
        <!--Mysql连接驱动-->
        <dependency>
            <groupId>mysql</groupId>
            <artifactId>mysql-connector-java</artifactId>
            <version>5.1.6</version>
        </dependency>
        <!--mybatis-->
        <dependency>
            <groupId>org.mybatis</groupId>
            <artifactId>mybatis</artifactId>
            <version>3.5.6</version>
        </dependency>
        <!--日志解析lo4j-->
        <dependency>
            <groupId>log4j</groupId>
            <artifactId>log4j</artifactId>
            <version>1.2.17</version>
        </dependency>
    </dependencies>

</project>
  • 创建两个实体类,与SQL表的变量一一对应
package com.wdzl.pojo;

/**
 * 账户类
 */
public class Account {
    
    
    private int aid;
    private int uid;
    private double money;
    private User user;
    //一个账户对应一个用户
    public Account() {
    
    
    }


    public Account(int aid, int uid, double money, User user) {
    
    
        this.aid = aid;
        this.uid = uid;
        this.money = money;
        this.user = user;
    }

    public int getAid() {
    
    
        return aid;
    }

    public void setAid(int aid) {
    
    
        this.aid = aid;
    }

    public int getUid() {
    
    
        return uid;
    }

    public void setUid(int uid) {
    
    
        this.uid = uid;
    }

    public double getMoney() {
    
    
        return money;
    }

    public void setMoney(double money) {
    
    
        this.money = money;
    }

    public User getUser() {
    
    
        return user;
    }

    public void setUser(User user) {
    
    
        this.user = user;
    }

    @Override
    public String toString() {
    
    
        return "Account{" +
                "aid=" + aid +
                ", uid=" + uid +
                ", money=" + money +
                ", user=" + user +
                '}';
    }
}

package com.wdzl.pojo;

import java.util.List;

/**
 *  用户类
 * @author lp
 * @version 1.0
 */
public class User {
    
    
    private int uid;
    private String username;
    private String sex;
    private String birthday;
    private String address;
    //一个用户可以有多个账户
    private List<Account> accounts;

    public User() {
    
    
    }

    public User(int uid, String username, String sex, String birthday, String address, List<Account> accounts) {
    
    
        this.uid = uid;
        this.username = username;
        this.sex = sex;
        this.birthday = birthday;
        this.address = address;
        this.accounts = accounts;
    }

    public int getUid() {
    
    
        return uid;
    }

    public void setUid(int uid) {
    
    
        this.uid = uid;
    }

    public String getUsername() {
    
    
        return username;
    }

    public void setUsername(String username) {
    
    
        this.username = username;
    }

    public String getSex() {
    
    
        return sex;
    }

    public void setSex(String sex) {
    
    
        this.sex = sex;
    }

    public String getBirthday() {
    
    
        return birthday;
    }

    public void setBirthday(String birthday) {
    
    
        this.birthday = birthday;
    }

    public String getAddress() {
    
    
        return address;
    }

    public void setAddress(String address) {
    
    
        this.address = address;
    }

    public List<Account> getAccounts() {
    
    
        return accounts;
    }

    public void setAccounts(List<Account> accounts) {
    
    
        this.accounts = accounts;
    }

    @Override
    public String toString() {
    
    
        return "User{" +
                "uid=" + uid +
                ", username='" + username + '\'' +
                ", sex='" + sex + '\'' +
                ", birthday='" + birthday + '\'' +
                ", address='" + address + '\'' +
                ", accounts=" + accounts +
                '}';
    }
}
  • 创建接口
/**
 *  操作用户实体类的接口
 */
public interface UserDao {
    
    
    /**
     * 查询用户列表
     * @return
     */
    List<User> findAll();
}
/**
 * 操作账户表的接口
 */
public interface AccountDao {
    
    
    /**
     * 查询账户列表
     * @return
     */
    List<Account> findAll();
}
  • 创建接口对应的xml配置文件
    • AccountDao.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.wdzl.dao.AccountDao"><!--对应dao层接口的全限定类名-->
    <resultMap id="accountUserMap" type="account">
        <id property="aid" column="aid"></id>
        <result property="uid" column="uid"></result>
        <result property="money" column="money"></result>
<!--        配置一对一关系映射-->
    <association property="user" column="uid" javaType="user">
        <id property="uid" column="uid"></id>
        <result property="username" column="username"></result>
        <result property="birthday" column="birthday"></result>
        <result property="sex" column="sex"></result>
        <result property="address" column="address"></result>
    </association>
    </resultMap>
    <select id="findAll" resultMap="accountUserMap">
        select a.aid,a.money,u.uid,u.username,u.sex,u.address from  account a,User u where u.uid = a.uid
    </select>
</mapper>

UserDao.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.wdzl.dao.UserDao"><!--对应dao层接口的全限定类名-->
    <resultMap id="userAccountMap" type="user">
        <id property="uid" column="uid"></id>
        <result property="username" column="username"></result>
        <result property="birthday" column="birthday"></result>
        <result property="sex" column="sex"></result>
        <result property="address" column="address"></result>
        
        <collection property="accounts" ofType="account" column="id">
            <id property="aid" column="aid"></id>
            <result property="uid" column="uid"></result>
            <result property="money" column="money"></result>
        </collection>
    </resultMap>
    <select id="findAll" resultMap="userAccountMap">
        select * from user u  left outer join account a on u.uid = a.uid
    </select>
</mapper>
  • 创建总配置文件
<?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>
    <typeAliases>
        <!--        <typeAlias type="com.wdzl.pojo.User" alias="aa"></typeAlias>-->
        <package name="com.wdzl.pojo" />
    </typeAliases>
    <!-- 配置环境 -->
    <environments default="mysql">
        <environment id="mysql">
            <!--配置事务的类型-->
            <transactionManager type="JDBC"></transactionManager>
            <!--配置数据源-->
            <dataSource type="POOLED">
                <!--配置连接数据库的4个基本信息-->
                <property name="driver" value="com.mysql.jdbc.Driver"/>
                <property name="url" value="jdbc:mysql://localhost:3306/mybatis2?useUnicode=true&amp;characterEncoding=utf-8"/>
                <property name="username" value="root"/>
                <property name="password" value="200429@wbnb"/>
            </dataSource>
        </environment>
    </environments>

    <mappers>
        <mapper resource="com/wdzl/dao/UserDao.xml"/>
        <mapper resource="com/wdzl/dao/AccountDao.xml"/>
    </mappers>

</configuration>
  • test
package com.wdzl.dao;

import com.wdzl.pojo.Account;
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.After;
import org.junit.Before;
import org.junit.Test;

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

public class AccountDaoTest {
    
    
    InputStream is;
    SqlSessionFactory factory;
    SqlSession sqlSession;
    AccountDao accountDao;

    /**
     * 初始化
     * @throws IOException
     */
    @Before
    public void init() throws IOException {
    
    
        //1.读取配置文件
        is = Resources.getResourceAsStream("SqlMapConfig.xml");
        //2.创建SqlSessionFactory工厂
        SqlSessionFactoryBuilder builder = new SqlSessionFactoryBuilder();
        factory = builder.build(is);
        //3.用工厂生产SqlSession对象
        sqlSession = factory.openSession();
        //4.使用SqlSession对象创建dao层的代理对象
        accountDao = sqlSession.getMapper(AccountDao.class);
    }

    /**
     * 释放资源
     * @throws IOException
     */
    @After
    public void destroy() throws IOException {
    
    
        sqlSession.close();
        is.close();
    }
    @Test
    public void testFindAll(){
    
    
        List<Account> accountDaos = accountDao.findAll();
        for (Account a: accountDaos){
    
    
            System.out.println(a);
        }
    }
}

package com.wdzl.dao;

import com.wdzl.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.After;
import org.junit.Before;
import org.junit.Test;

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

/**
 *  UserDao测试类
 * @author lp
 * @version 1.0
 * MyBatis入门案例测试实现步骤
 *      1. 读取配置文件
 *      2.创建SqlSessionFactory工厂
 *      3.用工厂生产SqlSession对象
 *      4.使用SqlSession对象创建dao层的代理对象
 *      5.使用代理对象执行方法
 *      6.释放资源
 */
public class UserDaoTest {
    
    
    InputStream is;
    SqlSessionFactory factory;
    SqlSession sqlSession;
    UserDao userDao;

    /**
     * 初始化
     * @throws IOException
     */
    @Before
    public void init() throws IOException {
    
    
        //1.读取配置文件
        is = Resources.getResourceAsStream("SqlMapConfig.xml");
        //2.创建SqlSessionFactory工厂
        SqlSessionFactoryBuilder builder = new SqlSessionFactoryBuilder();
        factory = builder.build(is);
        //3.用工厂生产SqlSession对象
        sqlSession = factory.openSession();
        //4.使用SqlSession对象创建dao层的代理对象
       userDao = sqlSession.getMapper(UserDao.class);
    }

    /**
     * 释放资源
     * @throws IOException
     */
    @After
    public void destroy() throws IOException {
    
    
        sqlSession.close();
        is.close();
    }
    @Test
    public void testFindAll(){
    
    
        List<User> users = userDao.findAll();
        for (User u:users){
    
    
            System.out.println(u);
        }
    }
}

SQL中的四张表

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-C8UK08E5-1616916840108)(C:\Users\dell\Pictures\java截图\Account.png)]

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-4kAJflUe-1616916840109)(C:\Users\dell\Pictures\java截图\role.png)]

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-o741phtW-1616916840110)(C:\Users\dell\Pictures\java截图\User.png)]

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-ASCLmnRu-1616916840111)(C:\Users\dell\Pictures\java截图\user-role.png)]

一对一实现了,多对一自然也实现了

d.3多表查询一对多

与上面类似,不同的是要User实体类上简历一个List集合

//一个用户可以有多个账户
private List<Account> accounts;

为了不造成代码的冗余,这一次我用注解方法来写

  • 导入依赖
  • 创建实体类(前面一斤刚提到过)
  • 建立接口

AccountDao

package com.wdzl.dao;

import com.wdzl.pojo.Account;
import org.apache.ibatis.annotations.One;
import org.apache.ibatis.annotations.Result;
import org.apache.ibatis.annotations.Results;
import org.apache.ibatis.annotations.Select;
import org.apache.ibatis.mapping.FetchType;

import java.util.List;

/**
 * 操作账户表的接口
 */
public interface AccountDao {
    
    
    /**
     * 查询账户列表
     * @return
     */
    @Select("select * from account")
    @Results(id = "accountMap",value = {
    
    
            @Result(id = true,column = "aid",property = "aid"),
            @Result(column = "uid",property = "uid"),
            @Result(column = "money",property = "money"),
            @Result(column = "uid",property = "user",one = @One(
                    select = "com.wdzl.dao.UserDao.findUserByUid",
                    fetchType = FetchType.EAGER
            ))
    })
    List<Account> findAll();

    @Select("select *from account where uid=#{uid}")
    Account findAccountByUid(Integer uid);
}

UserDao

package com.wdzl.dao;


import com.wdzl.pojo.User;
import org.apache.ibatis.annotations.*;
import org.apache.ibatis.mapping.FetchType;

import java.util.List;

/**
 *  操作用户实体类的接口
 */
@CacheNamespace(blocking = true)//开启二级缓存
public interface UserDao {
    
    
    /**
     * 查询用户列表
     * @return
     */
    @Select("select * from user")
    @Results(id = "userMap",value = {
    
    
            @Result(id = true,column = "uid",property = "uid"),
            @Result(column = "username",property = "username"),
            @Result(column = "birthday",property = "birthday"),
            @Result(column = "sex",property = "sex"),
            @Result(column = "address",property = "address"),
            @Result(property ="accounts",
                    column = "uid",
                    many = @Many(select = "com.wdzl.dao.AccountDao.findAccountByUid",
                            fetchType = FetchType.LAZY))
    })
    List<User> findAll();

    @Select("select *from user where uid=#{uid}")
    User findUserByUid(Integer uid);
}

  • 建立总配置文件
<?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>
    <typeAliases>
        <package name="com.wdzl.pojo" />
    </typeAliases>
    <!-- 配置环境 -->
    <environments default="mysql">
        <environment id="mysql">
            <!--配置事务的类型-->
            <transactionManager type="JDBC"></transactionManager>
            <!--配置数据源-->
            <dataSource type="POOLED">
                <!--配置连接数据库的4个基本信息-->
                <property name="driver" value="com.mysql.jdbc.Driver"/>
                <property name="url" value="jdbc:mysql://localhost:3306/mybatis2?useUnicode=true&amp;characterEncoding=utf-8"/>
                <property name="username" value="root"/>
                <property name="password" value="200429@wbnb"/>
            </dataSource>
        </environment>
    </environments>

    <mappers>
        <package name="com.wdzl.dao"/>
    </mappers>

</configuration>

test

package com.wdzl.dao;

import com.wdzl.pojo.Account;
import com.wdzl.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.After;
import org.junit.Before;
import org.junit.Test;

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

/**
 *  UserDao测试类
 * @author lp
 * @version 1.0
 * MyBatis入门案例测试实现步骤
 *      1. 读取配置文件
 *      2.创建SqlSessionFactory工厂
 *      3.用工厂生产SqlSession对象
 *      4.使用SqlSession对象创建dao层的代理对象
 *      5.使用代理对象执行方法
 *      6.释放资源
 */
public class UserDaoTest {
    
    
    InputStream is;
    SqlSessionFactory factory;
    SqlSession sqlSession;
    UserDao userDao;

    /**
     * 初始化
     * @throws IOException
     */
    @Before
    public void init() throws IOException {
    
    
        //1.读取配置文件
        is = Resources.getResourceAsStream("SqlMapConfig.xml");
        //2.创建SqlSessionFactory工厂
        SqlSessionFactoryBuilder builder = new SqlSessionFactoryBuilder();
        factory = builder.build(is);
        //3.用工厂生产SqlSession对象
        sqlSession = factory.openSession();
        //4.使用SqlSession对象创建dao层的代理对象
       userDao = sqlSession.getMapper(UserDao.class);
    }

    /**
     * 释放资源
     * @throws IOException
     */
    @After
    public void destroy() throws IOException {
    
    
        sqlSession.close();
        is.close();
    }
    @Test
    public void testFindAll(){
    
    
        List<User> users = userDao.findAll();
        for (User u:users){
    
    
            System.out.println(u);
        }
    }
    @Test
    public void testFindUserByUid(){
    
    
        User user = userDao.findUserByUid(2);
        System.out.println(user);
    }
}

d.4多表查询多对多

  • 导入依赖
  • 创建实体类(所用的表和上一例相同)
package com.wdzl.pojo;

import java.util.List;

public class Role {
    
    
    private int rid;
    private String roleName;
    private String roleDesc;
    //一个角色可以赋予多个用户
    private List<User> users;

    public Role() {
    
    
    }

    public Role(int rid, String roleName, String roleDesc) {
    
    
        this.rid = rid;
        this.roleName = roleName;
        this.roleDesc = roleDesc;
    }

    public List<User> getUsers() {
    
    
        return users;
    }

    public void setUsers(List<User> users) {
    
    
        this.users = users;
    }

    public int getRid() {
    
    
        return rid;
    }

    public void setRid(int rid) {
    
    
        this.rid = rid;
    }

    public String getRoleName() {
    
    
        return roleName;
    }

    public void setRoleName(String roleName) {
    
    
        this.roleName = roleName;
    }

    public String getRoleDesc() {
    
    
        return roleDesc;
    }

    public void setRoleDesc(String roleDesc) {
    
    
        this.roleDesc = roleDesc;
    }

    @Override
    public String toString() {
    
    
        return "Role{" +
                "rid=" + rid +
                ", roleName='" + roleName + '\'' +
                ", roleDesc='" + roleDesc + '\'' +
                '}';
    }
}

package com.wdzl.pojo;

import java.util.List;

/**
 *  学生类
 * @author lp
 * @version 1.0
 */
public class User {
    
    
    private int uid;
    private String username;
    private String sex;
    private String birthday;
    private String address;
    //一个用户可以有多个账户
    private List<Role> roles;
    //一个用户对应多个角色


    public User() {
    
    
    }

    public User(int uid, String username, String sex, String birthday, String address, List<Role> roles) {
    
    
        this.uid = uid;
        this.username = username;
        this.sex = sex;
        this.birthday = birthday;
        this.address = address;
        this.roles = roles;
    }

    public int getUid() {
    
    
        return uid;
    }

    public void setUid(int uid) {
    
    
        this.uid = uid;
    }

    public String getUsername() {
    
    
        return username;
    }

    public void setUsername(String username) {
    
    
        this.username = username;
    }

    public String getSex() {
    
    
        return sex;
    }

    public void setSex(String sex) {
    
    
        this.sex = sex;
    }

    public String getBirthday() {
    
    
        return birthday;
    }

    public void setBirthday(String birthday) {
    
    
        this.birthday = birthday;
    }

    public String getAddress() {
    
    
        return address;
    }

    public void setAddress(String address) {
    
    
        this.address = address;
    }

    public List<Role> getRoles() {
    
    
        return roles;
    }

    public void setRoles(List<Role> roles) {
    
    
        this.roles = roles;
    }

    @Override
    public String toString() {
    
    
        return "User{" +
                "uid=" + uid +
                ", username='" + username + '\'' +
                ", sex='" + sex + '\'' +
                ", birthday='" + birthday + '\'' +
                ", address='" + address + '\'' +
                ", roles=" + roles +
                '}';
    }
}


package com.wdzl.pojo;

public class UserRole {
    
    
    private int uid;
    private int rid;

    public UserRole() {
    
    
    }

    public UserRole(int uid, int rid) {
    
    
        this.uid = uid;
        this.rid = rid;
    }

    @Override
    public String toString() {
    
    
        return "UserRole{" +
                "uid=" + uid +
                ", rid=" + rid +
                '}';
    }

    public int getUid() {
    
    
        return uid;
    }

    public void setUid(int uid) {
    
    
        this.uid = uid;
    }

    public int getRid() {
    
    
        return rid;
    }

    public void setRid(int rid) {
    
    
        this.rid = rid;
    }
}

  • 建立接口(使用xml方式)
package com.wdzl.dao;

import com.wdzl.pojo.Role;

import java.util.List;

public interface RoleDao {
    
    
    List<Role> findAll();
}

package com.wdzl.dao;


import com.wdzl.pojo.User;

import java.util.List;

/**
 *  操作用户实体类的接口
 */
public interface UserDao {
    
    
    /**
     * 查询用户列表
     * @return
     */
    List<User> findAll();
}

  • 建立接口配置文件
<?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.wdzl.dao.RoleDao"><!--对应dao层接口的全限定类名-->
    <resultMap id="roleMap" type="role">
        <id property="rid" column="rid"/>
        <result property="roleName" column="ROLE_NAME"/>
        <result property="roleDesc" column="ROLE_DESC"/>
        <collection property="users" ofType="user" column="uid">
            <id property="uid" column="uid"></id>
            <result property="username" column="username"></result>
            <result property="birthday" column="birthday"></result>
            <result property="sex" column="sex"></result>
            <result property="address" column="address"></result>
        </collection>
    </resultMap>
    <!--查询用户表-->
    <select id="findAll" resultMap="roleMap">
         SELECT r.*,u.* FROM role r
         LEFT OUTER JOIN user_role ur ON r.rid = ur.rid
         LEFT OUTER JOIN USER u ON u.uid = ur.uid
    </select>
</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.wdzl.dao.UserDao"><!--对应dao层接口的全限定类名-->
    <resultMap id="userMap" type="user">
        <id property="uid" column="uid"></id>
        <result property="username" column="username"></result>
        <result property="birthday" column="birthday"></result>
        <result property="sex" column="sex"></result>
        <result property="address" column="address"></result>
         <collection property="roles" ofType="role" column="rid">
             <id property="rid" column="rid"/>
             <result property="roleName" column="ROLE_NAME"/>
             <result property="roleDesc" column="ROLE_DESC"/>
         </collection>
    </resultMap>
    <select id="findAll" resultMap="userMap">
--         select * from user u  left outer join account a on u.uid = a.uid
   SELECT u.*,r.* FROM USER u
         LEFT OUTER JOIN user_role ur ON u.uid = ur.uid
         LEFT OUTER JOIN role r ON r.rid = ur.rid
    </select>
</mapper>

test

package com.wdzl.dao;


import com.wdzl.pojo.Role;
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.After;
import org.junit.Before;
import org.junit.Test;

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

public class RoleDaoTest {
    
    
    InputStream is;
    SqlSessionFactory factory;
    SqlSession sqlSession;
    RoleDao roleDao;

    /**
     * 初始化
     * @throws IOException
     */
    @Before
    public void init() throws IOException {
    
    
        //1.读取配置文件
        is = Resources.getResourceAsStream("SqlMapConfig.xml");
        //2.创建SqlSessionFactory工厂
        SqlSessionFactoryBuilder builder = new SqlSessionFactoryBuilder();
        factory = builder.build(is);
        //3.用工厂生产SqlSession对象
        sqlSession = factory.openSession();
        //4.使用SqlSession对象创建dao层的代理对象
        roleDao = sqlSession.getMapper(RoleDao.class);
    }

    /**
     * 释放资源
     * @throws IOException
     */
    @After
    public void destroy() throws IOException {
    
    
        sqlSession.close();
        is.close();
    }
    @Test
    public void testFindAll(){
    
    
        List<Role> roles = roleDao.findAll();
        for (Role r: roles){
    
    
            System.out.println("--------------");
            System.out.println(r);
            System.out.println(r.getUsers());
        }
    }
}

package com.wdzl.dao;

import com.wdzl.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.After;
import org.junit.Before;
import org.junit.Test;

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

/**
 *  UserDao测试类
 * @author lp
 * @version 1.0
 * MyBatis入门案例测试实现步骤
 *      1. 读取配置文件
 *      2.创建SqlSessionFactory工厂
 *      3.用工厂生产SqlSession对象
 *      4.使用SqlSession对象创建dao层的代理对象
 *      5.使用代理对象执行方法
 *      6.释放资源
 */
public class UserDaoTest {
    
    
    InputStream is;
    SqlSessionFactory factory;
    SqlSession sqlSession;
    UserDao userDao;

    /**
     * 初始化
     * @throws IOException
     */
    @Before
    public void init() throws IOException {
    
    
        //1.读取配置文件
        is = Resources.getResourceAsStream("SqlMapConfig.xml");
        //2.创建SqlSessionFactory工厂
        SqlSessionFactoryBuilder builder = new SqlSessionFactoryBuilder();
        factory = builder.build(is);
        //3.用工厂生产SqlSession对象
        sqlSession = factory.openSession();
        //4.使用SqlSession对象创建dao层的代理对象
       userDao = sqlSession.getMapper(UserDao.class);
    }

    /**
     * 释放资源
     * @throws IOException
     */
    @After
    public void destroy() throws IOException {
    
    
        sqlSession.close();
        is.close();
    }
    @Test
    public void testFindAll(){
    
    
        List<User> users = userDao.findAll();
        for (User u:users){
    
    
            System.out.println("----------");
            System.out.println(u);
            System.out.println(u.getRoles());
        }
    }
}

e.缓存

概述

存在于内存中的数据叫缓存

应用

减少和数据库的交互,提高执行效率

适用

  1. 经常查询并且不经常改变的
  2. 对最终结果影响不大的

不适用

  1. 经常改变的数据
  2. 数据的最终结果对结果影响很大的(银行汇率,股票价格)

分类:mybatis中分为一级缓存二级缓存

e.1一级缓存

概述:

它指的是MyBatis中的SqlSession对象的缓存,当我们执行查询后,查询结果会存入到SqlSession为我们提供的一款存储区域中,该区域的存储结构为Map,当我们再次查询同样的数据时,MyBatis首先去一级缓存中查询,如果存在,则直接拿取使用

注意:

当SqlSession对象消失时,MyBatis的一级缓存也会小时

案例

缓存的案例与之前的区别不大,但要在主配置文件开启懒加载

    <!--设置懒加载-->
<settings>
    <setting name="lazyLoadingEnabled" value="true"/><!--开启懒加载-->
</settings>

**test1.0:**如下userDao获取了两遍id关于对象

   @Test
    public void testFirstLevelCache(){
    
    
        //执行查询
        User user = userDao.findUserById(1);
        System.out.println(user);
        User user2 = userDao.findUserById(1);
        System.out.println(user2);
        System.out.println("-----------");
        System.out.println(user==user2);

    }

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-cbEuo4SS-1616916840115)(C:\Users\dell\Pictures\java截图\懒加载图片1.png)]

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-2ZIgE2OL-1616916840115)(C:\Users\dell\Pictures\java截图\懒加载执行图例1.png)]

从以上执行结果来看,获取了两次userDao,执行后的两次结果相同,两相比较也确实时同一个数据,但是我们看第二个图片,当我们第一次执行的结果查询,获取数据后,电脑发现第二个数据与第一个数据相同,这样idea并没有再一次与数据库交互,而是直接将第一个数据再一次返回回来,这样就减少了与数据库交互

test2.0

    @Test
    public void testFirstLevelCache(){
    
    
        //执行查询
        User user = userDao.findUserById(1);
        System.out.println(user);
        sqlSession.close();//关闭一级缓存
        //重新获取sqlSession
        SqlSession sqlSession2 = factory.openSession();
        UserDao userDao2 = sqlSession2.getMapper(UserDao.class);
        User user2 = userDao2.findUserById(1);
        System.out.println(user2);
        System.out.println("-----------");
        System.out.println(user==user2);

    }

而如果我们执行的是以上的代码,可以看到我们将第一次缓存关闭,重新获取SqlSession,这样它又会重新与数据库进行交互

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-zy809QjU-1616916840115)(C:\Users\dell\Pictures\java截图\懒加载图片2.png)]

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-WEiwMdQb-1616916840116)(C:\Users\dell\Pictures\java截图\懒加载执行图例2.0.png)]

e.2二级缓存

概述:

它指的是MyBatis中SqlSessionFactory对象的缓存,在同一个SqlSessionFactory对象创建的SqlSession对象共享二级缓存

开启二级缓存

1.主配置文件中开启二级缓存

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

2.在映射配置文件中开启二级缓存

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

3.在映射配置文件标签里添加属性useCache=“true”

比如我的

    <select id="findUserById" parameterType="int" resultType="user"      useCache="true">
        select * from user where uid=#{
    
    uid}
    </select>
  • 一级与二级缓存的区别1

    • 一级缓存是SqlSession对象的缓存
    • 二级缓存是SqlSessionFactory对象的缓存(SqlSessionFactory可以生产SqlSession对象)
    • 我人推测如果有三级缓存,那就是对SqlSessionFactoryBuilder对象的缓存,但是目前MyBatis只有一二级缓存
  • 区别2

    • 一级缓存只需要在主配置文件中开启
    • 二级缓存却更复杂,不仅需要在主配置文件中开启,还要再mapper标签下的namespace对应的区域在做一个标签和属性

个人总结

  • MyBatis的实现主要有两个,一个是XML方式的实现,一个是注解方式的实现,二者虽然方法不同,但是殊途同归,而且再使用时也没有太多限制,可以相互使用,这个主要看个人了,如果要了解注释的实现方式可以看d.3多表查询一对多,如果要了解其他方式,我在以上的其他例子都是XML方式实现

ser2);
System.out.println("-----------");
System.out.println(user==user2);

}

[外链图片转存中...(img-cbEuo4SS-1616916840115)]

[外链图片转存中...(img-2ZIgE2OL-1616916840115)]

**<font color='orange'>从以上执行结果来看,获取了两次userDao,执行后的两次结果相同,两相比较也确实时同一个数据,但是我们看第二个图片,当我们第一次执行的结果查询,获取数据后,电脑发现第二个数据与第一个数据相同,这样idea并没有再一次与数据库交互,而是直接将第一个数据再一次返回回来,这样就减少了与数据库交互</font>**

**test2.0**

```java
    @Test
    public void testFirstLevelCache(){
        //执行查询
        User user = userDao.findUserById(1);
        System.out.println(user);
        sqlSession.close();//关闭一级缓存
        //重新获取sqlSession
        SqlSession sqlSession2 = factory.openSession();
        UserDao userDao2 = sqlSession2.getMapper(UserDao.class);
        User user2 = userDao2.findUserById(1);
        System.out.println(user2);
        System.out.println("-----------");
        System.out.println(user==user2);

    }

而如果我们执行的是以上的代码,可以看到我们将第一次缓存关闭,重新获取SqlSession,这样它又会重新与数据库进行交互

[外链图片转存中…(img-zy809QjU-1616916840115)]

[外链图片转存中…(img-WEiwMdQb-1616916840116)]

e.2二级缓存

概述:

它指的是MyBatis中SqlSessionFactory对象的缓存,在同一个SqlSessionFactory对象创建的SqlSession对象共享二级缓存

开启二级缓存

1.主配置文件中开启二级缓存

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

2.在映射配置文件中开启二级缓存

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

3.在映射配置文件标签里添加属性useCache=“true”

比如我的

    <select id="findUserById" parameterType="int" resultType="user"      useCache="true">
        select * from user where uid=#{
    
    uid}
    </select>
  • 一级与二级缓存的区别1

    • 一级缓存是SqlSession对象的缓存
    • 二级缓存是SqlSessionFactory对象的缓存(SqlSessionFactory可以生产SqlSession对象)
    • 我人推测如果有三级缓存,那就是对SqlSessionFactoryBuilder对象的缓存,但是目前MyBatis只有一二级缓存
  • 区别2

    • 一级缓存只需要在主配置文件中开启
    • 二级缓存却更复杂,不仅需要在主配置文件中开启,还要再mapper标签下的namespace对应的区域在做一个标签和属性

个人总结

  • MyBatis的实现主要有两个,一个是XML方式的实现,一个是注解方式的实现,二者虽然方法不同,但是殊途同归,而且再使用时也没有太多限制,可以相互使用,这个主要看个人了,如果要了解注释的实现方式可以看d.3多表查询一对多,如果要了解其他方式,我在以上的其他例子都是XML方式实现

  • MyBatis就是与数据库交互的一项技术,但它更加优于JDBC,也可以说它将JDBC的过程进行了一个封装,省去了这个过程

猜你喜欢

转载自blog.csdn.net/m0_52563687/article/details/115281772