一、流行框架介绍(Mybatis框架详解(含底层原理介绍))

一、常用框架个功能结构图

在这里插入图片描述

二、Mybatis框架的概述

mybatis 是一个优秀的基于 java 的持久层框架,它内部封装了 jdbc,使开发者只需要关注 sql 语句本身,而不需要花费精力去处理加载驱动、创建连接、创建 statement 等繁杂的过程。

mybatis 通过 xml 或注解的方式将要执行的各种 statement 配置起来,并通过 java 对象和 statement 中sql 的动态参数进行映射生成最终执行的 sql 语句,最后由 mybatis 框架执行 sql 并将结果映射为 java 对象并返回。

采用 ORM 思想解决了实体和数据库映射的问题,对 jdbc 进行了封装,屏蔽了 jdbc api 底层访问细节,使我们不用与 jdbc api 打交道,就可以完成对数据库的持久化操作。

为了我们能够更好掌握框架运行的内部过程,并且有更好的体验,下面我们将从自定义 Mybatis 框架开始来学习框架。此时我们将会体验框架从无到有的过程体验,也能够很好的综合前面阶段所学的基础。

三、ORM(Object Relational Mappging 对象关系映射)

简单的说:
就是把数据库表和实体类及实体类的属性对应起来,让我们可以操作实体类就实现操作数据库表。

user表中的字段User实体中的属性
iduserId
user_nameuserName

四、Mybatis入门案例

1. 数据库准备

DROP TABLE IF EXISTS user;
CREATE TABLE user (
id INT(11) NOT NULL AUTO_INCREMENT,
username VARCHAR(32) NOT NULL COMMENT ‘用户名称’,
birthday DATETIME DEFAULT NULL COMMENT ‘生日’,
sex CHAR(1) DEFAULT NULL COMMENT ‘性别’,
address VARCHAR(256) DEFAULT NULL COMMENT ‘地址’,
  PRIMARY KEY (id)
) ENGINE=INNODB DEFAULT CHARSET=utf8;
INSERT INTO user(id,username,birthday,sex,address) VALUES (41,‘老王’,‘2018-02-27 17:47:08’,‘男’,‘北京’),(42,‘小二王’,‘2018-03-02 15:09:37’,‘女’,‘北京朝阳区’),(43,‘小二王’,‘2018-03-04 11:34:34’,‘女’,‘北京昌平区’),(45,‘柯基侦探’,‘2018-03-04 12:04:06’,‘男’,‘北京大兴区’),(46,‘老王’,‘2018-03-07 17:37:26’,‘男’,‘北京’),(48,‘小马宝莉’,‘2018-03-08 11:44:00’,‘女’,‘北京东城’);
在这里插入图片描述

2. Mybatis的入门案例

项目结构
在这里插入图片描述

⑴ 创建maven工程并导入坐标

<?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.kejizhentan</groupId>
    <artifactId>mybatis-project</artifactId>
    <version>1.0-SNAPSHOT</version>
    <packaging>jar</packaging>
    <dependencies>
        <!--Mybatis框架的依赖-->
        <dependency>
            <groupId>org.mybatis</groupId>
            <artifactId>mybatis</artifactId>
            <version>3.4.5</version>
        </dependency>
        <!--mysql数据库驱动的依赖-->
        <dependency>
            <groupId>mysql</groupId>
            <artifactId>mysql-connector-java</artifactId>
            <version>5.1.6</version>
        </dependency>
        <!--生成日志文件的依赖-->
        <dependency>
            <groupId>log4j</groupId>
            <artifactId>log4j</artifactId>
            <version>1.2.12</version>
        </dependency>
        <!--junit单元测试的依赖-->
        <dependency>
            <groupId>junit</groupId>
            <artifactId>junit</artifactId>
            <version>4.11</version>
            <scope>test</scope>
        </dependency>
    </dependencies>
</project>

⑵ 创建实体类和dao的接口

User.java

public class User implements Serializable {
    private Integer id;
    private String username;
    private Date birthday;
    private String sex;
    private String address;

    public Integer getId() {
        return id;
    }

    public void setId(Integer id) {
        this.id = id;
    }

    public String getUsername() {
        return username;
    }

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

    public Date getBirthday() {
        return birthday;
    }

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

    public String getSex() {
        return sex;
    }

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

    public String getAddress() {
        return address;
    }

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

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

IUserDao.java

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

⑶ 创建Mybatis的主配置文件

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">
<!--Mybatis的主配置文件-->
<configuration>
    <!--配置环境-->
    <environments default="mysql">
        <!--配置mysql环境-->
        <environment id="mysql">
            <!--配置事务的类型-->
            <transactionManager type="JDBC"></transactionManager>
            <!--配置数据源(连接池)-->
            <dataSource type="POOLED">
                <!--配置数据的四个基本信息-->
                <property name="driver" value="com.mysql.jdbc.Driver"/>
                <property name="url" value="jdbc:mysql://localhost:3306/db4"/>
                <property name="username" value="root"/>
                <property name="password" value="root"/>
            </dataSource>
        </environment>
    </environments>
    <!--指定映射配置文件的位置,映射配置文件指的是每个dao独立的配置文件-->
    <mappers>
        <mapper resource="com/kejizhentan/dao/IUserDao.xml"/>
    </mappers>
</configuration>

⑷ 创建映射配置文件

IUserDao.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.kejizhentan.dao.IUserDao">
    <!--配置查询所有-->
    <select id = "findAll" resultType="com.kejizhentan.bean.User">
        select * from user
    </select>
</mapper>

⑸ 测试类:

MybatisTest.java

public class MybatisTest {
    @Test
    public void test1(){
        InputStream is = null;
        SqlSession sqlSession = null;
        try {
            //1.读取配置文件
            is = Resources.getResourceAsStream("SqlMapConfig.xml");
            //2.创建SqlSessionFactory工厂
            SqlSessionFactoryBuilder builder = new SqlSessionFactoryBuilder();
            SqlSessionFactory factory = builder.build(is);
            //3.使用工厂生产SqlSession对象
            sqlSession  = factory.openSession();
            //4.使用SqlSession创建Dao接口的代理对象
            IUserDao userDao = sqlSession.getMapper(IUserDao.class);
            //5.使用代理对象执行方法
            List<User> users = userDao.findAll();
            for (User user : users) {
                System.out.println(user);
            }
        }catch (Exception e){
            e.printStackTrace();
        }finally {
            //6.释放资源
            if(sqlSession != null){
                 sqlSession.close();
            }
            try {
                if(is != null){
                    is.close();
                }
            }catch (Exception e){
                e.printStackTrace();
            }
        }
    }
}

执行结果如下:
在这里插入图片描述

注意事项:
环境搭建的注意事项:
① 创建IUserDao.xml 和 IUserDao.java时名称是为了和我们之前的知识保持一致。
在Mybatis中它把持久层的操作接口名称和映射文件也叫做:Mapper
所以:IUserDao 和 IUserMapper是一样的
② 在idea中创建目录的时候,它和包是不一样的
包在创建时:com.itheima.dao它是三级结构
目录在创建时:com.itheima.dao是一级目录
所以创建时要一步步分开创建 在这里插入图片描述

mybatis的映射配置文件位置必须和dao接口的包结构相同
映射配置文件的mapper标签namespace属性的取值必须是dao接口的全限定类名
映射配置文件的操作配置(select),id属性的取值必须是dao接口的方法名
当我们遵从了第③,④,⑤点之后,我们在开发中就无须再写dao的实现类
mybatis测试类中的注意事项:
不要忘记在映射配置中告知mybatis要封装到哪个实体类中
配置的方式:指定实体类的全限定类名

3. 使用注解来实现2中的入门案例

项目结构
在这里插入图片描述

⑴ 创建maven工程并导入坐标

<?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.kejizhentan</groupId>
    <artifactId>mybatis-project</artifactId>
    <version>1.0-SNAPSHOT</version>
    <packaging>jar</packaging>
    <dependencies>
        <!--Mybatis框架的依赖-->
        <dependency>
            <groupId>org.mybatis</groupId>
            <artifactId>mybatis</artifactId>
            <version>3.4.5</version>
        </dependency>
        <!--mysql数据库驱动的依赖-->
        <dependency>
            <groupId>mysql</groupId>
            <artifactId>mysql-connector-java</artifactId>
            <version>5.1.6</version>
        </dependency>
        <!--生成日志文件的依赖-->
        <dependency>
            <groupId>log4j</groupId>
            <artifactId>log4j</artifactId>
            <version>1.2.12</version>
        </dependency>
        <!--junit单元测试的依赖-->
        <dependency>
            <groupId>junit</groupId>
            <artifactId>junit</artifactId>
            <version>4.11</version>
            <scope>test</scope>
        </dependency>
    </dependencies>
</project>

⑵ 创建实体类和dao的接口

User.java

public class User implements Serializable {
    private Integer id;
    private String username;
    private Date birthday;
    private String sex;
    private String address;

    public Integer getId() {
        return id;
    }

    public void setId(Integer id) {
        this.id = id;
    }

    public String getUsername() {
        return username;
    }

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

    public Date getBirthday() {
        return birthday;
    }

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

    public String getSex() {
        return sex;
    }

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

    public String getAddress() {
        return address;
    }

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

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

IUserDao.java

public interface IUserDao {
    @Select("select * from user")
    List<User> findAll();
}

⑶ 创建Mybatis的主配置文件

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">
<!--Mybatis的主配置文件-->
<configuration>
    <!--配置环境-->
    <environments default="mysql">
        <!--配置mysql环境-->
        <environment id="mysql">
            <!--配置事务的类型-->
            <transactionManager type="JDBC"></transactionManager>
            <!--配置数据源(连接池)-->
            <dataSource type="POOLED">
                <!--配置数据的四个基本信息-->
                <property name="driver" value="com.mysql.jdbc.Driver"/>
                <property name="url" value="jdbc:mysql://localhost:3306/db4"/>
                <property name="username" value="root"/>
                <property name="password" value="root"/>
            </dataSource>
        </environment>
    </environments>
    <!--
     使用配置文件来实现mybatis的配置:
        指定映射配置文件的位置,映射配置文件指的是每个dao独立的配置文件
     使用注解来实现mybatis的配置:
        如果使用注解来配置的话,此处应该使用class属性指定被注解的dao全限制类名
    -->
    <mappers>
        <!--<mapper resource="com/kejizhentan/dao/IUserDao.xml"/>-->
        <mapper class="com.kejizhentan.dao.IUserDao"/>
    </mappers>
</configuration>

⑷ 测试类:

MybatisTest.java

public class MybatisTest {
    @Test
    public void test1(){
        InputStream is = null;
        SqlSession sqlSession = null;
        try {
            //1.读取配置文件
            is = Resources.getResourceAsStream("SqlMapConfig.xml");
            //2.创建SqlSessionFactory工厂
            SqlSessionFactoryBuilder builder = new SqlSessionFactoryBuilder();
            SqlSessionFactory factory = builder.build(is);
            //3.使用工厂生产SqlSession对象
            sqlSession  = factory.openSession();
            //4.使用SqlSession创建Dao接口的代理对象
            IUserDao userDao = sqlSession.getMapper(IUserDao.class);
            //5.使用代理对象执行方法
            List<User> users = userDao.findAll();
            for (User user : users) {
                System.out.println(user);
            }
        }catch (Exception e){
            e.printStackTrace();
        }finally {
            //6.释放资源
            if(sqlSession != null){
                 sqlSession.close();
            }
            try {
                if(is != null){
                    is.close();
                }
            }catch (Exception e){
                e.printStackTrace();
            }
        }
    }
}

执行结果如下:
在这里插入图片描述

mybatis基于注解的入门案例的步骤:
把IUserDao.xml移除,在dao接口的方法上使用@Select注解,并且指定SQL语句
同时需要在SqlMapConfig.xml中的mapper配置时,使用class属性指定dao接口的全限定类名
注意:
我们在实际开发中,都是越简便越好,所以都是采用不写dao实现类的方式。
不管使用XML还是注解配置。但是Mybatis它是支持写dao实现类的。

五、 自定义Mybatis框架(底层原理)

自定Mybatis框架的分析:
在这里插入图片描述
自定义Mybatis框架流程
在这里插入图片描述

1. 自定义mybatis框架所涉及的主要几个类

自定义mybatis能通过入门案例看到类
class Resources
class SqlSessionFactoryBuilder
interface SqlSessionFactory
interface SqlSession
在这里插入图片描述

2. 自定义Mybatis框架的项目结构

在这里插入图片描述

3. 自定义Mybatis框架详解

⑴ 实体类和dao的接口

User.java

public class User implements Serializable {
    private Integer id;
    private String username;
    private Date birthday;
    private String sex;
    private String address;

    public Integer getId() {
        return id;
    }

    public void setId(Integer id) {
        this.id = id;
    }

    public String getUsername() {
        return username;
    }

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

    public Date getBirthday() {
        return birthday;
    }

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

    public String getSex() {
        return sex;
    }

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

    public String getAddress() {
        return address;
    }

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

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

IUserDao.java

public interface IUserDao {
    @Select("select * from user")
    List<User> findAll();
}

⑵ 测试类MybatisTest :

public class MybatisTest {
    @Test
    public void test1(){
        InputStream is = null;
        SqlSession sqlSession = null;
        try {
            //1.读取配置文件
            is = Resources.getResourceAsStream("SqlMapConfig.xml");
            //2.创建SqlSessionFactory工厂
            SqlSessionFactoryBuilder builder = new SqlSessionFactoryBuilder();
            SqlSessionFactory factory = builder.build(is);
            //3.使用工厂生产SqlSession对象
            sqlSession  = factory.openSession();
            //4.使用SqlSession创建Dao接口的代理对象
            IUserDao userDao = sqlSession.getMapper(IUserDao.class);
            //5.使用代理对象执行方法
            List<User> users = userDao.findAll();
            for (User user : users) {
                System.out.println(user);
            }
        }catch (Exception e){
            e.printStackTrace();
        }finally {
            //6.释放资源
            if(sqlSession != null){
                 sqlSession.close();
            }
            try {
                if(is != null){
                    is.close();
                }
            }catch (Exception e){
                e.printStackTrace();
            }
        }
    }
}

⑶ 类加载器读取配置文件Resources类

/**
 *@Description 使用类加载器读取配置文件
 *@Author kejizhentan
 *@Date 2021/10/23 15:59
 */
public class Resources {
    /**
     * @Description 设置一个方法,根据传入的参数获取字节输入流
     * @Author kejizhentan
     * @Date 2021/10/23 16:02
     **/
    public static InputStream getResourceAsStream(String file){
        return Resources.class.getClassLoader().getResourceAsStream(file);
    }
}

⑷ 用于创建一个SqlSessionFactory对象的SqlSessionFactoryBuilder

/**
 *@Description 用于创建一个SqlSessionFactory对象
 *@Author kejizhentan
 *@Date 2021/10/23 16:20
 */
public class SqlSessionFactoryBuilder {
    /**
     * @Description 根据参数的字节输入流来构建一个SqlSessionFactory工厂
     * @Author kejizhentan
     * @Date 2021/10/23 16:18
     **/
    public SqlSessionFactory build(InputStream is){
        Configuration cfg = XMLConfigBuilder.loadConfiguration(is);
        return  new DefaultSqlSessionFactory(cfg);
    }
}

⑸ 用于打开一个新的SqlSession对象的SqlSessionFactory 接口及其实现类DefaultSqlSessionFactory

SqlSessionFactory 接口

public interface SqlSessionFactory {
    /**
     * @Description 用于打开一个新的SqlSession对象
     * @Author kejizhentan
     * @Date 2021/10/23 16:10
     **/
    SqlSession openSession();
}

实现类DefaultSqlSessionFactory

/**
 *@Description SqlSessionFactory接口的实现类
 *@Author kejizhentan
 *@Date 2021/10/23 17:10
 */
public class DefaultSqlSessionFactory implements SqlSessionFactory {
    private Configuration cfg;

    public DefaultSqlSessionFactory(Configuration cfg) {
        this.cfg = cfg;
    }

    /**
     * @Description 创建一个新的操作数据库的对象
     * @Author kejizhentan
     * @Date 2021/10/23 17:09
     **/
    public SqlSession openSession() {
        return new DefaultSqlSession(cfg);
    }
}

⑹ 自定义Mybatis中和数据库交互的核心接口SqlSession及其实现类DefaultSqlSession(这个最重要)

SqlSession接口:

/**
 *@Description 自定义Mybatis中和数据库交互的核心类
 * 它里面可以创建dao接口的代理对象
 *@Author kejizhentan
 *@Date 2021/10/23 16:11
 */
public interface SqlSession {
    /**
     * @Description 根据参数创建一个代理对象
     * @Author kejizhentan
     * @Date 2021/10/23 16:14
     * @Param dao的接口字节码
     **/
    <T> T getMapper(Class<T> daoInterfaceClass);
    /**
     * @Description 释放资源
     * @Author kejizhentan
     * @Date 2021/10/23 16:16
     **/
    void close();
}

DefaultSqlSession实现类:

/**
 *@Description SqlSession接口的实现类
 *@Author kejizhentan
 *@Date 2021/10/23 17:12
 */
public class DefaultSqlSession implements SqlSession {
    private Configuration cfg;
    private Connection conn;
    public DefaultSqlSession(Configuration cfg) {
        this.cfg = cfg;
        conn = DataSourceUtil.getConnection(cfg);
    }

    /**
     * @Description 用于创建代理对象
     * @Author kejizhentan
     * @Date 2021/10/23 17:12
     **/
    public <T> T getMapper(Class<T> daoInterfaceClass) {
        return (T)Proxy.newProxyInstance(daoInterfaceClass.getClassLoader(),
                new Class[]{daoInterfaceClass},
                new MapperProxy(cfg.getMappers(), conn));
    }

    /**
     * @Description 释放资源
     * @Author kejizhentan
     * @Date 2021/10/23 17:13
     **/
    public void close() {
        try {
            if(conn != null){
                conn.close();
            }
        } catch (SQLException e) {
            e.printStackTrace();
        }
    }
}

⑺ 动态代理的功能核心类MapperProxy

/**
 *@Description 动态代理的核心类
 *@Author kejizhentan
 *@Date 2021/10/23 20:24
 */
public class MapperProxy implements InvocationHandler {
    //map的key是全限定类名+方法名
    private Map<String, Mapper> mappers;
    private Connection conn;
    public MapperProxy(Map<String, Mapper> mappers,Connection conn) {
        this.mappers = mappers;
        this.conn = conn;
    }

    /**
     * @Description 用于对方法进行增强的,我们增强其实就是调用selectList方法
     * @Author kejizhentan
     * @Date 2021/10/23 17:24
     **/
    public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
        //1. 获取方法名
        String methodName = method.getName();
        //2. 获取方法所在类的名称
        String className = method.getDeclaringClass().getName();
        //3.组合key
        String key = className +"."+methodName;
        //4.获取mappers中的mapper对象
        Mapper mapper = mappers.get(key);
        //5.判断是否有mapper
        if(mapper == null){
            throw  new IllegalArgumentException("传入的参数有误");
        }
        //6.调用工具类执行查询所有
        return new Executor().selectList(mapper,conn);
    }
}

⑻ 自定义Mybatis的配置类Configuration

Configuration

/**
 *@Description 自定义Mybatis的配置类
 *@Author kejizhentan
 *@Date 2021/10/23 16:38
 */
public class Configuration {
    private String driver;
    private String url;
    private String username;
    private String password;
    Map<String, Mapper> mappers = new HashMap<String, Mapper>();
    public Map<String, Mapper> getMappers() {
        return mappers;
    }

    public void setMappers(Map<String, Mapper> mappers) {
        this.mappers.putAll(mappers);//此处需要使用追加的方式
    }

    public String getDriver() {
        return driver;
    }

    public void setDriver(String driver) {
        this.driver = driver;
    }

    public String getUrl() {
        return url;
    }

    public void setUrl(String url) {
        this.url = url;
    }

    public String getUsername() {
        return username;
    }

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

    public String getPassword() {
        return password;
    }

    public void setPassword(String password) {
        this.password = password;
    }
}

⑼ 用于封装执行的SQL语句和结果类型的全限定类名的Mapper类

/**
 *@Description 用于封装执行的SQL语句和结果类型的全限定类名
 *@Author kejizhentan
 *@Date 2021/10/23 16:41
 */
public class Mapper {
    private String queryString;//执行的SQL语句
    private String resultType;//实体类的全限定类名

    public String getQueryString() {
        return queryString;
    }

    public void setQueryString(String queryString) {
        this.queryString = queryString;
    }

    public String getResultType() {
        return resultType;
    }

    public void setResultType(String resultType) {
        this.resultType = resultType;
    }
}

⑽ 自定义Mybatis中使用到的工具类(这些工具类一般不属于核心代码部分)

用于创建数据源的工具类DataSourceUtil

/**
 *@Description 用于创建数据源的工具类
 *@Author kejizhentan
 *@Date 2021/10/23 17:48
 */
public class DataSourceUtil {
    /**
     * @Description 用于获取一个连接的方法
     * @Author kejizhentan
     * @Date 2021/10/23 17:50
     **/
    public static Connection getConnection(Configuration cfg) {
        try {
            Class.forName(cfg.getDriver());
            return DriverManager.getConnection(cfg.getUrl(), cfg.getUsername(), cfg.getPassword());
        } catch (Exception e) {
            throw new  RuntimeException(e);
        }
    }
}

负责执行SQL语句,并且封装结果集的工具类Executor

/**
 * @author kejizhentan
 * 负责执行SQL语句,并且封装结果集
 */
public class Executor {

    public <E> List<E> selectList(Mapper mapper, Connection conn) {
        PreparedStatement pstm = null;
        ResultSet rs = null;
        try {
            //1.取出mapper中的数据
            String queryString = mapper.getQueryString();//select * from user
            String resultType = mapper.getResultType();//com.itheima.domain.User
            Class domainClass = Class.forName(resultType);
            //2.获取PreparedStatement对象
            pstm = conn.prepareStatement(queryString);
            //3.执行SQL语句,获取结果集
            rs = pstm.executeQuery();
            //4.封装结果集
            List<E> list = new ArrayList<E>();//定义返回值
            while(rs.next()) {
                //实例化要封装的实体类对象
                E obj = (E)domainClass.newInstance();

                //取出结果集的元信息:ResultSetMetaData
                ResultSetMetaData rsmd = rs.getMetaData();
                //取出总列数
                int columnCount = rsmd.getColumnCount();
                //遍历总列数
                for (int i = 1; i <= columnCount; i++) {
                    //获取每列的名称,列名的序号是从1开始的
                    String columnName = rsmd.getColumnName(i);
                    //根据得到列名,获取每列的值
                    Object columnValue = rs.getObject(columnName);
                    //给obj赋值:使用Java内省机制(借助PropertyDescriptor实现属性的封装)
                    PropertyDescriptor pd = new PropertyDescriptor(columnName,domainClass);//要求:实体类的属性和数据库表的列名保持一种
                    //获取它的写入方法
                    Method writeMethod = pd.getWriteMethod();
                    //把获取的列的值,给对象赋值
                    writeMethod.invoke(obj,columnValue);
                }
                //把赋好值的对象加入到集合中
                list.add(obj);
            }
            return list;
        } catch (Exception e) {
            throw new RuntimeException(e);
        } finally {
            release(pstm,rs);
        }
    }


    private void release(PreparedStatement pstm,ResultSet rs){
        if(rs != null){
            try {
                rs.close();
            }catch(Exception e){
                e.printStackTrace();
            }
        }

        if(pstm != null){
            try {
                pstm.close();
            }catch(Exception e){
                e.printStackTrace();
            }
        }
    }
}

dom4j工具类XMLConfigBuilder,用于解析xml

/**
 *@Description dom4j工具类,用于解析xml
 *@Author kejizhentan
 *@Date 2021/10/23 16:26
 */
public class XMLConfigBuilder {
    /**
     * 解析主配置文件,把里面的内容填充到DefaultSqlSession所需要的地方
     * 使用的技术:
     *      dom4j+xpath
     */
    public static Configuration loadConfiguration(InputStream config){
        try{
            //定义封装连接信息的配置对象(mybatis的配置对象)
            Configuration cfg = new Configuration();

            //1.获取SAXReader对象
            SAXReader reader = new SAXReader();
            //2.根据字节输入流获取Document对象
            Document document = reader.read(config);
            //3.获取根节点
            Element root = document.getRootElement();
            //4.使用xpath中选择指定节点的方式,获取所有property节点
            List<Element> propertyElements = root.selectNodes("//property");
            //5.遍历节点
            for(Element propertyElement : propertyElements){
                //判断节点是连接数据库的哪部分信息
                //取出name属性的值
                String name = propertyElement.attributeValue("name");
                if("driver".equals(name)){
                    //表示驱动
                    //获取property标签value属性的值
                    String driver = propertyElement.attributeValue("value");
                    cfg.setDriver(driver);
                }
                if("url".equals(name)){
                    //表示连接字符串
                    //获取property标签value属性的值
                    String url = propertyElement.attributeValue("value");
                    cfg.setUrl(url);
                }
                if("username".equals(name)){
                    //表示用户名
                    //获取property标签value属性的值
                    String username = propertyElement.attributeValue("value");
                    cfg.setUsername(username);
                }
                if("password".equals(name)){
                    //表示密码
                    //获取property标签value属性的值
                    String password = propertyElement.attributeValue("value");
                    cfg.setPassword(password);
                }
            }
            //取出mappers中的所有mapper标签,判断他们使用了resource还是class属性
            List<Element> mapperElements = root.selectNodes("//mappers/mapper");
            //遍历集合
            for(Element mapperElement : mapperElements){
                //判断mapperElement使用的是哪个属性
                Attribute attribute = mapperElement.attribute("resource");
                if(attribute != null){
                    System.out.println("使用的是XML");
                    //表示有resource属性,用的是XML
                    //取出属性的值
                    String mapperPath = attribute.getValue();//获取属性的值"com/itheima/dao/IUserDao.xml"
                    //把映射配置文件的内容获取出来,封装成一个map
                    Map<String, Mapper> mappers = loadMapperConfiguration(mapperPath);
                    //给configuration中的mappers赋值
                    cfg.setMappers(mappers);
                }else{
                    System.out.println("使用的是注解");
                    //表示没有resource属性,用的是注解
                    //获取class属性的值
                    String daoClassPath = mapperElement.attributeValue("class");
                    //根据daoClassPath获取封装的必要信息
                    Map<String,Mapper> mappers = loadMapperAnnotation(daoClassPath);
                    //给configuration中的mappers赋值
                    cfg.setMappers(mappers);
                }
            }
            //返回Configuration
            return cfg;
        }catch(Exception e){
            throw new RuntimeException(e);
        }finally{
            try {
                config.close();
            }catch(Exception e){
                e.printStackTrace();
            }
        }

    }

    /**
     * 根据传入的参数,解析XML,并且封装到Map中
     * @param mapperPath    映射配置文件的位置
     * @return  map中包含了获取的唯一标识(key是由dao的全限定类名和方法名组成)
     *          以及执行所需的必要信息(value是一个Mapper对象,里面存放的是执行的SQL语句和要封装的实体类全限定类名)
     */
    private static Map<String,Mapper> loadMapperConfiguration(String mapperPath)throws IOException {
        InputStream in = null;
        try{
            //定义返回值对象
            Map<String,Mapper> mappers = new HashMap<String,Mapper>();
            //1.根据路径获取字节输入流
            in = Resources.getResourceAsStream(mapperPath);
            //2.根据字节输入流获取Document对象
            SAXReader reader = new SAXReader();
            Document document = reader.read(in);
            //3.获取根节点
            Element root = document.getRootElement();
            //4.获取根节点的namespace属性取值
            String namespace = root.attributeValue("namespace");//是组成map中key的部分
            //5.获取所有的select节点
            List<Element> selectElements = root.selectNodes("//select");
            //6.遍历select节点集合
            for(Element selectElement : selectElements){
                //取出id属性的值      组成map中key的部分
                String id = selectElement.attributeValue("id");
                //取出resultType属性的值  组成map中value的部分
                String resultType = selectElement.attributeValue("resultType");
                //取出文本内容            组成map中value的部分
                String queryString = selectElement.getText();
                //创建Key
                String key = namespace+"."+id;
                //创建Value
                Mapper mapper = new Mapper();
                mapper.setQueryString(queryString);
                mapper.setResultType(resultType);
                //把key和value存入mappers中
                mappers.put(key,mapper);
            }
            return mappers;
        }catch(Exception e){
            throw new RuntimeException(e);
        }finally{
            in.close();
        }
    }

    /**
     * 根据传入的参数,得到dao中所有被select注解标注的方法。
     * 根据方法名称和类名,以及方法上注解value属性的值,组成Mapper的必要信息
     * @param daoClassPath
     * @return
     */
    private static Map<String,Mapper> loadMapperAnnotation(String daoClassPath)throws Exception{
        //定义返回值对象
        Map<String,Mapper> mappers = new HashMap<String, Mapper>();

        //1.得到dao接口的字节码对象
        Class daoClass = Class.forName(daoClassPath);
        //2.得到dao接口中的方法数组
        Method[] methods = daoClass.getMethods();
        //3.遍历Method数组
        for(Method method : methods){
            //取出每一个方法,判断是否有select注解
            boolean isAnnotated = method.isAnnotationPresent(Select.class);
            if(isAnnotated){
                //创建Mapper对象
                Mapper mapper = new Mapper();
                //取出注解的value属性值
                Select selectAnno = method.getAnnotation(Select.class);
                String queryString = selectAnno.value();
                mapper.setQueryString(queryString);
                //获取当前方法的返回值,还要求必须带有泛型信息
                Type type = method.getGenericReturnType();//List<User>
                //判断type是不是参数化的类型
                if(type instanceof ParameterizedType){
                    //强转
                    ParameterizedType ptype = (ParameterizedType)type;
                    //得到参数化类型中的实际类型参数
                    Type[] types = ptype.getActualTypeArguments();
                    //取出第一个
                    Class domainClass = (Class)types[0];
                    //获取domainClass的类名
                    String resultType = domainClass.getName();
                    //给Mapper赋值
                    mapper.setResultType(resultType);
                }
                //组装key的信息
                //获取方法的名称
                String methodName = method.getName();
                String className = method.getDeclaringClass().getName();
                String key = className+"."+methodName;
                //给map赋值
                mappers.put(key,mapper);
            }
        }
        return mappers;
    }
}

⑾ 自定义的查询注解@Select

/**
 *@Description 查询的注解
 *@Author kejizhentan
 *@Date 2021/10/23 19:20
 */
@Retention(RetentionPolicy.RUNTIME)
@Target(ElementType.METHOD)
public @interface Select {
    /**
     * @Description 配置SQL语句的方法
     * @Author kejizhentan
     * @Date 2021/10/23 19:21
     **/
    String value();
}

⑿ 使用XML配置查询时用的IUserDao.xml配置文件

<?xml version="1.0" encoding="UTF-8"?>
<mapper namespace="com.kejizhentan.dao.IUserDao">
    <!--配置查询所有-->
    <select id = "findAll" resultType="com.kejizhentan.bean.User">
        select * from user
    </select>
</mapper>

⒀ 主配置文件SqlMapConfig.xml

<!--Mybatis的主配置文件-->
<configuration>
    <!--配置环境-->
    <environments default="mysql">
        <!--配置mysql环境-->
        <environment id="mysql">
            <!--配置事务的类型-->
            <transactionManager type="JDBC"></transactionManager>
            <!--配置数据源(连接池)-->
            <dataSource type="POOLED">
                <!--配置数据的四个基本信息-->
                <property name="driver" value="com.mysql.jdbc.Driver"/>
                <property name="url" value="jdbc:mysql://localhost:3306/db4"/>
                <property name="username" value="root"/>
                <property name="password" value="root"/>
            </dataSource>
        </environment>
    </environments>
    <!--
     使用配置文件来实现mybatis的配置:
        指定映射配置文件的位置,映射配置文件指的是每个dao独立的配置文件
     使用注解来实现mybatis的配置:
        如果使用注解来配置的话,此处应该使用class属性指定被注解的dao全限制类名
    -->
    <mappers>
        <!--<mapper resource="com/kejizhentan/dao/IUserDao.xml"/>-->
        <mapper class="com.kejizhentan.dao.IUserDao"/>
    </mappers>
</configuration>

⒁ 执行结果如下:

在这里插入图片描述

点击下载自定义Mybatis框架的完整项目

六、 Mybatis的CRUD操作

项目结构:
在这里插入图片描述

⑴ 创建maven工程并导入坐标

<?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.kejizhentan</groupId>
    <artifactId>mybatis-project</artifactId>
    <version>1.0-SNAPSHOT</version>
    <packaging>jar</packaging>
    <dependencies>
        <!--Mybatis框架的依赖-->
        <dependency>
            <groupId>org.mybatis</groupId>
            <artifactId>mybatis</artifactId>
            <version>3.4.5</version>
        </dependency>
        <!--mysql数据库驱动的依赖-->
        <dependency>
            <groupId>mysql</groupId>
            <artifactId>mysql-connector-java</artifactId>
            <version>5.1.6</version>
        </dependency>
        <!--生成日志文件的依赖-->
        <dependency>
            <groupId>log4j</groupId>
            <artifactId>log4j</artifactId>
            <version>1.2.12</version>
        </dependency>
        <!--junit单元测试的依赖-->
        <dependency>
            <groupId>junit</groupId>
            <artifactId>junit</artifactId>
            <version>4.11</version>
            <scope>test</scope>
        </dependency>
    </dependencies>
</project>

⑵ 创建实体类和dao的接口

User.java

public class User implements Serializable {
    private Integer id;
    private String username;
    private Date birthday;
    private String sex;
    private String address;

    public Integer getId() {
        return id;
    }

    public void setId(Integer id) {
        this.id = id;
    }

    public String getUsername() {
        return username;
    }

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

    public Date getBirthday() {
        return birthday;
    }

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

    public String getSex() {
        return sex;
    }

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

    public String getAddress() {
        return address;
    }

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

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

IUserDao.java

/**
 *@Description 用户的持久化接口
 *@Author kejizhentan
 *@Date 2021/10/24 12:51
 */
public interface IUserDao {
    /**
     * @Description 查询所有用户的方法
     * @Author kejizhentan
     * @Date 2021/10/24 12:51
     **/
    List<User> findAll();

    /**
     * @Description 保存用户
     * @Author kejizhentan
     * @Date 2021/10/24 13:24
     **/
    void saveUser(User user);
    /**
     * @Description 更新用户的操作
     * @Author kejizhentan
     * @Date 2021/10/24 13:24
     */
    void updateUser(User user);
    /**
     * @Description 根据id删除用户的操作
     * @Author kejizhentan
     * @Date 2021/10/24 13:56
     **/
    void deleteUser(Integer userId);
    /**
     * @Description 根据id查询用户信息
     * @Author kejizhentan
     * @Date 2021/10/24 13:24
     */
    User findById(Integer userId);
    /**
     * @Description 根据名称模糊查询用户信息
     * @Author kejizhentan
     * @Date 2021/10/24 13:24
     */
    List<User> findByName(String username);
    /**
     * @Description 查询总用户数
     * @Author kejizhentan
     * @Date 2021/10/24 13:24
     */
    int findTotal();
}

⑶ 创建Mybatis的主配置文件

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">
<!--Mybatis的主配置文件-->
<configuration>
    <!--配置环境-->
    <environments default="mysql">
        <!--配置mysql环境-->
        <environment id="mysql">
            <!--配置事务的类型-->
            <transactionManager type="JDBC"></transactionManager>
            <!--配置数据源(连接池)-->
            <dataSource type="POOLED">
                <!--配置数据的四个基本信息-->
                <property name="driver" value="com.mysql.jdbc.Driver"/>
                <property name="url" value="jdbc:mysql://localhost:3306/db4"/>
                <property name="username" value="root"/>
                <property name="password" value="root"/>
            </dataSource>
        </environment>
    </environments>
    <!--指定映射配置文件的位置,映射配置文件指的是每个dao独立的配置文件-->
    <mappers>
        <mapper resource="com/kejizhentan/dao/IUserDao.xml"/>
    </mappers>
</configuration>

⑷ 创建映射配置文件

IUserDao.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.kejizhentan.dao.IUserDao">
    <!--配置查询所有-->
    <select id = "findAll" resultType="com.kejizhentan.bean.User">
        select * from user
    </select>
    <!-- 保存用户 -->
    <insert id="saveUser" parameterType="com.kejizhentan.bean.User">
        insert into user(username,address,sex,birthday)values(#{username},#{address},#{sex},#{birthday});
    </insert>
     <!-- 更新用户 -->
    <update id="updateUser" parameterType="com.kejizhentan.bean.User">
        update user set username=#{username},address=#{address},sex=#{sex},birthday=#{birthday} where id=#{id}
    </update>
    <!-- 根据id删除用户-->
    <delete id="deleteUser" parameterType="java.lang.Integer">
        delete from user where id = #{uid}
    </delete>
      <!-- 根据id查询用户 -->
    <select id="findById" parameterType="int" resultType="com.kejizhentan.bean.User">
        select * from user where id = #{uid}
    </select>
     <!-- 根据名称模糊查询 -->
    <select id="findByName" parameterType="string" resultType="com.kejizhentan.bean.User">
          <!--select * from user where username like #{name}-->
         <!--select * from user where username like '%${value}%'-->
         select * from user where username like concat('%',#{name},'%')
    </select>
    <!-- 获取用户的总记录条数 -->
    <select id="findTotal" resultType="int">
        select count(id) from user;
    </select>
</mapper>

⑸ 测试类:

MybatisTest.java

/**
 *@Description mybatis的CRUD测试类
 *@Author kejizhentan
 *@Date 2021/10/24 14:37
 */
public class MybatisTest {
    private InputStream is;
    private SqlSession sqlSession;
    private IUserDao userDao;
    /**
     * @Description 初始化加载资源的方法
     * @Author kejizhentan
     * @Date 2021/10/24 13:34
     **/
    @Before//用于在执行方法执行之前执行
    public void init(){
        try {
            //1.读取配置文件
            is = Resources.getResourceAsStream("SqlMapConfig.xml");
            //2.创建SqlSessionFactory工厂
            SqlSessionFactoryBuilder builder = new SqlSessionFactoryBuilder();
            SqlSessionFactory factory = builder.build(is);
            //3.使用工厂生产SqlSession对象
            sqlSession  = factory.openSession();
            //4.使用SqlSession创建Dao接口的代理对象
            userDao = sqlSession.getMapper(IUserDao.class);
        }catch (Exception e){
            e.printStackTrace();
        }
    }
    /**
     * @Description 释放资源的方法
     * @Author kejizhentan
     * @Date 2021/10/24 13:34
     **/
    @After//用于在测试方法执行之后执行
    public void close(){
        //提交事务
        sqlSession.commit();
        //6.释放资源
        if(sqlSession != null){
            sqlSession.close();
        }
        try {
            if(is != null){
                is.close();
            }
        }catch (Exception e){
            e.printStackTrace();
        }
    }
    /**
     * @Description 查询所有用户的操作
     * @Author kejizhentan
     * @Date 2021/10/24 13:51
     **/
    @Test
    public void findAll(){
            //5.使用代理对象执行方法
            List<User> users = userDao.findAll();
            for (User user : users) {
                System.out.println(user);
            }
    }
    /**
     * @Description 新增用户的操作
     * @Author kejizhentan
     * @Date 2021/10/24 13:52
     **/
    @Test
    public void saveUser(){
        //实例化对象
        User user = new User();
        user.setUsername("李云迪");
        user.setAddress("朝阳区");
        user.setBirthday(new Date());
        user.setSex("男");
        //6.使用代理对象执行方法
        userDao.saveUser(user);
    }
    /**
     * @Description 更新用户的操作
     * @Author kejizhentan
     * @Date 2021/10/24 13:52
     **/
    @Test
    public void updateUser(){
        //实例化对象
        User user = new User();
        user.setId(52);
        user.setUsername("朝阳群众");
        user.setAddress("朝阳区");
        user.setBirthday(new Date());
        user.setSex("女");
        //6.使用代理对象执行方法
        userDao.updateUser(user);
    }
    /**
     * @Description 根据Id删除用户
     * @Author kejizhentan
     * @Date 2021/10/24 13:52
     */
    @Test
    public void deleteUser(){
        userDao.deleteUser(52);
    }
    /**
     * @Description 根据Id查询用户的方法
     * @Author kejizhentan
     * @Date 2021/10/24 13:52
     */
    @Test
    public void findById(){
        User user = userDao.findById(45);
        System.out.println(user);
    }
    /**
     * @Description 根据姓名模糊查询
     * @Author kejizhentan
     * @Date 2021/10/24 13:52
     */
    @Test
    public void findByName(){
        //List<User> users = userDao.findByName("%王%");
        List<User> users = userDao.findByName("王");
        for (User user : users) {
            System.out.println(user);
        }
    }
    /**
     * @Description 查询用户信息总条数
     * @Author kejizhentan
     * @Date 2021/10/24 13:52
     */
    @Test
    public void findTotal(){
        int num = userDao.findTotal();
        System.out.println("一共"+num+"条数据");
    }
}

注意事项:
Mybatis中#{}和${}的区别i:
在这里插入图片描述

七、 Mybatis中的细节

1. 获取新增数据的id

<!-- 保存用户 -->
<insert id="saveUser" parameterType="com.kejizhentan.bean.User">
    <!--配置插入操作后,获取插入数据的id-->
    <selectKey keyProperty="id" keyColumn="id" resultType="int" order="AFTER">
           select last_insert_id()
    </selectKey>
    insert into user(username,address,sex,birthday)values(#{username},#{address},#{sex},#{birthday})
</insert>

结果如下:
在这里插入图片描述

2. Mybatis框架中OGNL表达式使用介绍

OGNL全称是Object Graphic Navigation Language
       对象   图   导航    语言
它是通过对象的取值方法来获取数据。在写法上把get给省略了。
比如我们获取用户的名称
类中的写法:user.getUsername();
OGNL表达式写法:user.username

mybatis中为什么能直接写username,而不用user.呢?
因为在parameterType中已经提供了属性所属的类,所以此时不需要写对象名
在这里插入图片描述

例如:需求:根据用户名查询用户信息,查询条件放到 QueryVo 的 user 属性中。
QueryVo.java

public class QueryVo {
    private User user;

    public User getUser() {
        return user;
    }

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

User.java

public class User implements Serializable {
    private Integer id;
    private String username;
    private Date birthday;
    private String sex;
    private String address;

    public Integer getId() {
        return id;
    }

    public void setId(Integer id) {
        this.id = id;
    }

    public String getUsername() {
        return username;
    }

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

    public Date getBirthday() {
        return birthday;
    }

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

    public String getSex() {
        return sex;
    }

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

    public String getAddress() {
        return address;
    }

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

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

在这里插入图片描述

3. Mybatis中对象中的属性和表中的字段对应不上的问题

在这里插入图片描述

⑴ 解决方式一:起别名的方式(这种方式执行效率最高)

在这里插入图片描述

⑵ 解决方式二:配置表的列名和实体的属性名的对应关系

在这里插入图片描述

4. Mybatis中的细节中的详细代码

项目结构:
在这里插入图片描述

⑴ 创建maven工程并导入坐标

<?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.kejizhentan</groupId>
    <artifactId>mybatis-project</artifactId>
    <version>1.0-SNAPSHOT</version>
    <packaging>jar</packaging>
    <dependencies>
        <!--Mybatis框架的依赖-->
        <dependency>
            <groupId>org.mybatis</groupId>
            <artifactId>mybatis</artifactId>
            <version>3.4.5</version>
        </dependency>
        <!--mysql数据库驱动的依赖-->
        <dependency>
            <groupId>mysql</groupId>
            <artifactId>mysql-connector-java</artifactId>
            <version>5.1.6</version>
        </dependency>
        <!--生成日志文件的依赖-->
        <dependency>
            <groupId>log4j</groupId>
            <artifactId>log4j</artifactId>
            <version>1.2.12</version>
        </dependency>
        <!--junit单元测试的依赖-->
        <dependency>
            <groupId>junit</groupId>
            <artifactId>junit</artifactId>
            <version>4.11</version>
            <scope>test</scope>
        </dependency>
    </dependencies>
</project>

⑵ 创建实体类和dao的接口

User.java

public class User implements Serializable {
    private Integer userId;
    private String userName;
    private Date userBirthday;
    private String userSex;
    private String userAddress;

    public Integer getUserId() {
        return userId;
    }

    public void setUserId(Integer userId) {
        this.userId = userId;
    }

    public String getUserName() {
        return userName;
    }

    public void setUserName(String userName) {
        this.userName = userName;
    }

    public Date getUserBirthday() {
        return userBirthday;
    }

    public void setUserBirthday(Date userBirthday) {
        this.userBirthday = userBirthday;
    }

    public String getUserSex() {
        return userSex;
    }

    public void setUserSex(String userSex) {
        this.userSex = userSex;
    }

    public String getUserAddress() {
        return userAddress;
    }

    public void setUserAddress(String userAddress) {
        this.userAddress = userAddress;
    }

    @Override
    public String toString() {
        return "User{" +
                "userId=" + userId +
                ", userName='" + userName + '\'' +
                ", userBirthday=" + userBirthday +
                ", userSex='" + userSex + '\'' +
                ", userAddress='" + userAddress + '\'' +
                '}';
    }
}

QueryVo.java

public class QueryVo {
    private User user;

    public User getUser() {
        return user;
    }

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

IUserDao.java

/**
 *@Description 用户的持久化接口
 *@Author kejizhentan
 *@Date 2021/10/24 12:51
 */
public interface IUserDao {
    /**
     * @Description 查询所有用户的方法
     * @Author kejizhentan
     * @Date 2021/10/24 12:51
     **/
    List<User> findAll();

    /**
     * @Description 保存用户
     * @Author kejizhentan
     * @Date 2021/10/24 13:24
     **/
    void saveUser(User user);
    /**
     * @Description OGNL的介绍通过QueryVo查询user
     * @Author kejizhentan                
     * @Date 2021/10/24 16:50
     **/
    User findUserByQueryVo(QueryVo queryVo);

}

⑶ 创建Mybatis的主配置文件

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">
<!--Mybatis的主配置文件-->
<configuration>
    <!--配置环境-->
    <environments default="mysql">
        <!--配置mysql环境-->
        <environment id="mysql">
            <!--配置事务的类型-->
            <transactionManager type="JDBC"></transactionManager>
            <!--配置数据源(连接池)-->
            <dataSource type="POOLED">
                <!--配置数据的四个基本信息-->
                <property name="driver" value="com.mysql.jdbc.Driver"/>
                <property name="url" value="jdbc:mysql://localhost:3306/db4"/>
                <property name="username" value="root"/>
                <property name="password" value="root"/>
            </dataSource>
        </environment>
    </environments>
    <!--指定映射配置文件的位置,映射配置文件指的是每个dao独立的配置文件-->
    <mappers>
        <mapper resource="com/kejizhentan/dao/IUserDao.xml"/>
    </mappers>
</configuration>

⑷ 创建映射配置文件

IUserDao.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.kejizhentan.dao.IUserDao">
    <!--配置表的列名和实体的属性名的对应关系-->
    <resultMap id="userMap" type="com.kejizhentan.bean.User">
        <!--主键字段的对应-->
        <id property="userId" column="id"></id>
        <!--非主键字段的对应-->
        <result property="userName" column="username"></result>
        <result property="userAddress" column="address"></result>
        <result property="userSex" column="sex"></result>
        <result property="userBirthday" column="birthday"></result>
    </resultMap>
    <!--配置查询所有-->
    <select id = "findAll" resultMap="userMap">
        <!--select id as userId, username as userName, birthday as userBirthday, sex as userSex, address as userAddress from user-->
        select * from user
    </select>
    <!-- 保存用户 -->
    <insert id="saveUser" parameterType="com.kejizhentan.bean.User">
        <!--配置插入操作后,获取插入数据的id-->
        <selectKey keyProperty="userId" keyColumn="id" resultType="int" order="AFTER">
               select last_insert_id()
        </selectKey>
        insert into user(username,address,sex,birthday)values(#{userName},#{userAddress},#{userSex},#{userBirthday})
        <!--insert into user(username,address,sex,birthday)values(#{username},#{address},#{sex},#{birthday})-->
    </insert>
    <!--OGNL的介绍通过QueryVo查询user-->
    <select id="findUserByQueryVo" parameterType="com.kejizhentan.bean.QueryVo"  resultMap="userMap">
            select * from user where id = #{user.userId}
    </select>
</mapper>

⑸ 测试类:

MybatisTest.java

/**
 *@Description mybatis的CRUD测试类
 *@Author kejizhentan
 *@Date 2021/10/24 14:37
 */
public class MybatisTest {
    private InputStream is;
    private SqlSession sqlSession;
    private IUserDao userDao;
    /**
     * @Description 初始化加载资源的方法
     * @Author kejizhentan
     * @Date 2021/10/24 13:34
     **/
    @Before//用于在执行方法执行之前执行
    public void init(){
        try {
            //1.读取配置文件
            is = Resources.getResourceAsStream("SqlMapConfig.xml");
            //2.创建SqlSessionFactory工厂
            SqlSessionFactoryBuilder builder = new SqlSessionFactoryBuilder();
            SqlSessionFactory factory = builder.build(is);
            //3.使用工厂生产SqlSession对象
            sqlSession  = factory.openSession();
            //4.使用SqlSession创建Dao接口的代理对象
            userDao = sqlSession.getMapper(IUserDao.class);
        }catch (Exception e){
            e.printStackTrace();
        }
    }
    /**
     * @Description 释放资源的方法
     * @Author kejizhentan
     * @Date 2021/10/24 13:34
     **/
    @After//用于在测试方法执行之后执行
    public void close(){
        //提交事务
        sqlSession.commit();
        //6.释放资源
        if(sqlSession != null){
            sqlSession.close();
        }
        try {
            if(is != null){
                is.close();
            }
        }catch (Exception e){
            e.printStackTrace();
        }
    }
    /**
     * @Description 查询所有用户的操作
     * @Author kejizhentan
     * @Date 2021/10/24 13:51
     **/
    @Test
    public void findAll(){
            //5.使用代理对象执行方法
            List<User> users = userDao.findAll();
            for (User user : users) {
                System.out.println(user);
            }
    }
    /**
     * @Description 新增用户的操作
     * @Author kejizhentan
     * @Date 2021/10/24 13:52
     **/
    @Test
    public void saveUser(){
        //实例化对象
        User user = new User();
        user.setUserName("朝阳区人民");
        user.setUserAddress("朝阳区");
        user.setUserBirthday(new Date());
        user.setUserSex("男");
        System.out.println("保存之前的user"+user);
        //6.使用代理对象执行方法
        userDao.saveUser(user);
        System.out.println("保存之后的user"+user);
    }

    /**
     * @Description OGNL表达式查询
     * @Author kejizhentan                
     * @Date 2021/10/24 16:21
     **/
    @Test
    public void findUserByQueryVo(){
        QueryVo queryVo = new QueryVo();
        User user = new User();
        user.setUserId(41);
        queryVo.setUser(user);
        User u = userDao.findUserByQueryVo(queryVo);
        System.out.println(u);
    }
}

八、 Mybatis使用代理对象执行sq的底层流程

在这里插入图片描述

九、 properties标签的使用细节

可以在标签内部配置连接数据库的信息,也可以通过属性引用外部配置文件信息
resource属性:常用的方式
  用于指定配置文件的位置,是按照类路径的写法来写的,并且必须存在于类路径下
url属性
 它要求按照URL的写法来写地址
URL:Uniform Resouece Locator 统一资源定位符。它可以唯一标识一个资源的位置。
    URI:Uniform Resource Identifier 统一资源标识符,它是应用中可以唯一定位一个资源的。

配置方式一:该方式太蠢,一般没人用,了解即可
在这里插入图片描述

配置方式二:通过resource属性配置(该方式比较常用)
在这里插入图片描述
配置方式三:通过url属性配置
在这里插入图片描述
在这里插入图片描述

注意:
文件使用URL定位的方式:
在这里插入图片描述

properties标签的使用细节详细代码:
项目结构:
在这里插入图片描述

⑴ 创建maven工程并导入坐标

<?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.kejizhentan</groupId>
    <artifactId>mybatis-easy</artifactId>
    <version>1.0-SNAPSHOT</version>
    <packaging>jar</packaging>
    <dependencies>
        <!--Mybatis框架的依赖-->
        <dependency>
            <groupId>org.mybatis</groupId>
            <artifactId>mybatis</artifactId>
            <version>3.4.5</version>
        </dependency>
        <!--mysql数据库驱动的依赖-->
        <dependency>
            <groupId>mysql</groupId>
            <artifactId>mysql-connector-java</artifactId>
            <version>5.1.6</version>
        </dependency>
        <!--生成日志文件的依赖-->
        <dependency>
            <groupId>log4j</groupId>
            <artifactId>log4j</artifactId>
            <version>1.2.12</version>
        </dependency>
        <!--junit单元测试的依赖-->
        <dependency>
            <groupId>junit</groupId>
            <artifactId>junit</artifactId>
            <version>4.11</version>
            <scope>test</scope>
        </dependency>
    </dependencies>
</project>

⑵ 创建实体类和dao的接口

User.java

public class User implements Serializable {
    private Integer id;
    private String username;
    private Date birthday;
    private String sex;
    private String address;

    public Integer getId() {
        return id;
    }

    public void setId(Integer id) {
        this.id = id;
    }

    public String getUsername() {
        return username;
    }

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

    public Date getBirthday() {
        return birthday;
    }

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

    public String getSex() {
        return sex;
    }

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

    public String getAddress() {
        return address;
    }

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

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

IUserDao.java

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

⑶ 创建Mybatis的主配置文件

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">
<!--Mybatis的主配置文件-->
<configuration>
    <!-- 配置properties
        可以在标签内部配置连接数据库的信息。也可以通过属性引用外部配置文件信息
        resource属性: 常用的
            用于指定配置文件的位置,是按照类路径的写法来写,并且必须存在于类路径下。
        url属性:
            是要求按照Url的写法来写地址
            URL:Uniform Resource Locator 统一资源定位符。它是可以唯一标识一个资源的位置。
            它的写法:
                http://localhost:8080/mybatisserver/demo1Servlet
                协议      主机     端口       URI

            URI:Uniform Resource Identifier 统一资源标识符。它是在应用中可以唯一定位一个资源的。
    -->
<!--    <properties resource="jdbcConfig.properties">-->
    <properties url="file:///C:/Users/Administrator/Desktop/jdbcConfig.properties">
<!--            <property name="driver" value="com.mysql.jdbc.Driver"/>-->
<!--            <property name="url" value="jdbc:mysql://localhost:3306/db4"/>-->
<!--            <property name="username" value="root"/>-->
<!--            <property name="password" value="root"/>-->
    </properties>
    <!--配置环境-->
    <environments default="mysql">
        <!--配置mysql环境-->
        <environment id="mysql">
            <!--配置事务的类型-->
            <transactionManager type="JDBC"></transactionManager>
            <!--配置数据源(连接池)-->
            <dataSource type="POOLED">
                <!--配置数据的四个基本信息-->
                <property name="driver" value="${jdbc.driver}"/>
                <property name="url" value="${jdbc.url}"/>
                <property name="username" value="${jdbc.username}"/>
                <property name="password" value="${jdbc.password}"/>
            </dataSource>
        </environment>
    </environments>
    <!--指定映射配置文件的位置,映射配置文件指的是每个dao独立的配置文件-->
    <mappers>
        <mapper resource="com/kejizhentan/dao/IUserDao.xml"/>
    </mappers>
</configuration>

jdbcConfig.properties配置文件:

jdbc.driver=com.mysql.jdbc.Driver
jdbc.url=jdbc:mysql://localhost:3306/db4
jdbc.username=root
jdbc.password=root

⑷ 创建映射配置文件

IUserDao.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.kejizhentan.dao.IUserDao">
    <!--配置查询所有-->
    <select id = "findAll" resultType="com.kejizhentan.bean.User">
        select * from user
    </select>
</mapper>

⑸ 测试类:

MybatisTest.java

public class MybatisTest {
    @Test
    public void test1(){
        InputStream is = null;
        SqlSession sqlSession = null;
        try {
            //1.读取配置文件
            is = Resources.getResourceAsStream("SqlMapConfig.xml");
            //2.创建SqlSessionFactory工厂
            SqlSessionFactoryBuilder builder = new SqlSessionFactoryBuilder();
            SqlSessionFactory factory = builder.build(is);
            //3.使用工厂生产SqlSession对象
            sqlSession  = factory.openSession();
            //4.使用SqlSession创建Dao接口的代理对象
            IUserDao userDao = sqlSession.getMapper(IUserDao.class);
            //5.使用代理对象执行方法
            List<User> users = userDao.findAll();
            for (User user : users) {
                System.out.println(user);
            }
        }catch (Exception e){
            e.printStackTrace();
        }finally {
            //6.释放资源
            if(sqlSession != null){
                sqlSession.close();
            }
            try {
                if(is != null){
                    is.close();
                }
            }catch (Exception e){
                e.printStackTrace();
            }
        }
    }
}

执行结果如下:
在这里插入图片描述

十、typeAliases标签和package标签

1. typeAliases标签和package标签配置别名

⑴ typeAliases标签配置别名

在这里插入图片描述

⑵ typeAliases标签+package标签配置别名

在这里插入图片描述

2. 使用package标签指定dao接口所在包

在这里插入图片描述

typeAliases标签和package标签使用详细代码

项目结构:
在这里插入图片描述

⑴ 创建maven工程并导入坐标

<?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.kejizhentan</groupId>
    <artifactId>mybatis-easy</artifactId>
    <version>1.0-SNAPSHOT</version>
    <packaging>jar</packaging>
    <dependencies>
        <!--Mybatis框架的依赖-->
        <dependency>
            <groupId>org.mybatis</groupId>
            <artifactId>mybatis</artifactId>
            <version>3.4.5</version>
        </dependency>
        <!--mysql数据库驱动的依赖-->
        <dependency>
            <groupId>mysql</groupId>
            <artifactId>mysql-connector-java</artifactId>
            <version>5.1.6</version>
        </dependency>
        <!--生成日志文件的依赖-->
        <dependency>
            <groupId>log4j</groupId>
            <artifactId>log4j</artifactId>
            <version>1.2.12</version>
        </dependency>
        <!--junit单元测试的依赖-->
        <dependency>
            <groupId>junit</groupId>
            <artifactId>junit</artifactId>
            <version>4.11</version>
            <scope>test</scope>
        </dependency>
    </dependencies>
</project>

⑵ 创建实体类和dao的接口

User.java

public class User implements Serializable {
    private Integer id;
    private String username;
    private Date birthday;
    private String sex;
    private String address;

    public Integer getId() {
        return id;
    }

    public void setId(Integer id) {
        this.id = id;
    }

    public String getUsername() {
        return username;
    }

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

    public Date getBirthday() {
        return birthday;
    }

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

    public String getSex() {
        return sex;
    }

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

    public String getAddress() {
        return address;
    }

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

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

IUserDao.java

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

⑶ 创建Mybatis的主配置文件

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">
<!--Mybatis的主配置文件-->
<configuration>
    <!--使用typeAliases配置别名,它只能配置bean中实体类的别名-->
    <typeAliases>
        <!--typeAlias用于配置别名,type属性指定的是实体全限定类名,alias属性指定别名,当制定了别名就不再区分大小写了-->
        <!--<typeAlias type="com.kejizhentan.bean.User" alias="user"></typeAlias>-->
        <!--用于指定要配置别名的包,当指定之后,该包下的实体类都会注册别名,并且类名就是别名,不再区分大小写-->
        <package name="com.kejizhentan.bean"/>
    </typeAliases>
    <!--配置环境-->
    <environments default="mysql">
        <!--配置mysql环境-->
        <environment id="mysql">
            <!--配置事务的类型-->
            <transactionManager type="JDBC"></transactionManager>
            <!--配置数据源(连接池)-->
            <dataSource type="POOLED">
                <!--配置数据的四个基本信息-->
                <property name="driver" value="com.mysql.jdbc.Driver"/>
                <property name="url" value="jdbc:mysql://localhost:3306/db4"/>
                <property name="username" value="root"/>
                <property name="password" value="root"/>
            </dataSource>
        </environment>
    </environments>
    <!--
    使用配置文件来实现mybatis的配置:
       指定映射配置文件的位置,映射配置文件指的是每个dao独立的配置文件
    使用注解来实现mybatis的配置:
       如果使用注解来配置的话,此处应该使用class属性指定被注解的dao全限制类名
    -->
    <mappers>
        <!--<mapper resource="com/kejizhentan/dao/IUserDao.xml"/>-->
        <!--<mapper class="com.kejizhentan.dao.IUserDao"/>-->
        <!--package标签是用于指定dao接口所在包,当指定之后就不需要再写mapper标签以及resource或者class了-->
        <package name="com.kejizhentan.dao"/>
    </mappers>
</configuration>

⑷ 创建映射配置文件

IUserDao.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.kejizhentan.dao.IUserDao">
    <!--配置查询所有-->
    <select id = "findAll" resultType="UseR">
        select * from user
    </select>
</mapper>

⑸ 测试类:

MybatisTest.java

public class MybatisTest {
    @Test
    public void test1(){
        InputStream is = null;
        SqlSession sqlSession = null;
        try {
            //1.读取配置文件
            is = Resources.getResourceAsStream("SqlMapConfig.xml");
            //2.创建SqlSessionFactory工厂
            SqlSessionFactoryBuilder builder = new SqlSessionFactoryBuilder();
            SqlSessionFactory factory = builder.build(is);
            //3.使用工厂生产SqlSession对象
            sqlSession  = factory.openSession();
            //4.使用SqlSession创建Dao接口的代理对象
            IUserDao userDao = sqlSession.getMapper(IUserDao.class);
            //5.使用代理对象执行方法
            List<User> users = userDao.findAll();
            for (User user : users) {
                System.out.println(user);
            }
        }catch (Exception e){
            e.printStackTrace();
        }finally {
            //6.释放资源
            if(sqlSession != null){
                sqlSession.close();
            }
            try {
                if(is != null){
                    is.close();
                }
            }catch (Exception e){
                e.printStackTrace();
            }
        }
    }
}

执行结果如下:
在这里插入图片描述

十一、Mybatis中的连接池

1. 连接池:

我们在实际开发中都会使用连接池。因为它可以减少我们获取连接所消耗的时间。

2. mybatis中的连接池

⑴ mybatis连接池提供了3种方式的配置:

  • 配置的位置
    主配置文件SqlMapConfig.xml中的dataSource标签,type属性就是表示采用何种连接池方式。
  • type属性的取值
    POOLED: 采用传统的javax.sql.DataSource规范中的连接池,mybatis中有针对规范的实现
    UNPOOLED: 采用传统的获取连接的方式,虽然也实现Javax.sql.DataSource接口,但是并没有使用池的思想。
    JNDI: 采用服务器提供的JNDI技术实现,来获取DataSource对象,不同的服务器所能拿到DataSource是不一样。注意:如果不是web或者maven的war工程,是不能使用的。(用于了解,不做过多的解释)

⑵ POOLED和UNPOOLED的比较

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

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

十二、Mybatis中自动提交设置

在这里插入图片描述

十三、Mybatis中动态sql的使用

1. if 标签的使用

在这里插入图片描述

2. if和where标签组合使用(此时可以省略where1=1的条件)

在这里插入图片描述

3. foreach遍历查询条件

在这里插入图片描述

Mybatis中动态sql的使用详细代码

项目结构
在这里插入图片描述

⑴ 创建maven工程并导入坐标

<?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.kejizhentan</groupId>
    <artifactId>mybatis-project</artifactId>
    <version>1.0-SNAPSHOT</version>
    <packaging>jar</packaging>
    <dependencies>
        <!--Mybatis框架的依赖-->
        <dependency>
            <groupId>org.mybatis</groupId>
            <artifactId>mybatis</artifactId>
            <version>3.4.5</version>
        </dependency>
        <!--mysql数据库驱动的依赖-->
        <dependency>
            <groupId>mysql</groupId>
            <artifactId>mysql-connector-java</artifactId>
            <version>5.1.6</version>
        </dependency>
        <!--生成日志文件的依赖-->
        <dependency>
            <groupId>log4j</groupId>
            <artifactId>log4j</artifactId>
            <version>1.2.12</version>
        </dependency>
        <!--junit单元测试的依赖-->
        <dependency>
            <groupId>junit</groupId>
            <artifactId>junit</artifactId>
            <version>4.11</version>
            <scope>test</scope>
        </dependency>
    </dependencies>
</project>

⑵ 创建实体类和dao的接口

User.java

public class User implements Serializable {
    private Integer id;
    private String username;
    private Date birthday;
    private String sex;
    private String address;

    public Integer getId() {
        return id;
    }

    public void setId(Integer id) {
        this.id = id;
    }

    public String getUsername() {
        return username;
    }

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

    public Date getBirthday() {
        return birthday;
    }

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

    public String getSex() {
        return sex;
    }

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

    public String getAddress() {
        return address;
    }

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

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

IUserDao.java

public interface IUserDao {
    /**
     * @Description 查询所有用户的方法
     * @Author kejizhentan
     * @Date 2021/10/24 12:51
     **/
    List<User> findAll();

    /**
     * @Description 根据id查询用户信息
     * @Author kejizhentan
     * @Date 2021/10/24 13:24
     */
    User findById(Integer userId);
    /**
     * @Description 根据名称模糊查询用户信息
     * @Author kejizhentan
     * @Date 2021/10/24 13:24
     */
    List<User> findByName(String username);
    /**
     * @Description OGNL的介绍通过QueryVo查询user
     * @Author kejizhentan
     * @Date 2021/10/24 16:50
     **/
    User findUserByQueryVo(QueryVo queryVo);
    /**
     * @Description 根据传入的参数条件来查询(查询条件不确定)
     * @Author kejizhentan
     * @Date 2021/10/30 21:51
     **/
    List<User> findUserByCondition(User user);

    /**
     * @Description 根据id集合,查询用户信息
     * @Author kejizhentan
     * @Date 2021/10/30 22:18
     **/
    List<User> findUserByIds(@Param("ids") List<Integer> ids);
}

⑶ 创建Mybatis的主配置文件

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">
<!--Mybatis的主配置文件-->
<configuration>
    <!--配置环境-->
    <environments default="mysql">
        <!--配置mysql环境-->
        <environment id="mysql">
            <!--配置事务的类型-->
            <transactionManager type="JDBC"></transactionManager>
            <!--配置数据源(连接池)-->
            <dataSource type="POOLED">
                <!--配置数据的四个基本信息-->
                <property name="driver" value="com.mysql.jdbc.Driver"/>
                <property name="url" value="jdbc:mysql://localhost:3306/db4"/>
                <property name="username" value="root"/>
                <property name="password" value="root"/>
            </dataSource>
        </environment>
    </environments>
    <!--
     使用配置文件来实现mybatis的配置:
        指定映射配置文件的位置,映射配置文件指的是每个dao独立的配置文件
     使用注解来实现mybatis的配置:
        如果使用注解来配置的话,此处应该使用class属性指定被注解的dao全限制类名
    -->
    <mappers>
        <mapper resource="com/kejizhentan/dao/IUserDao.xml"/>
        <!--<mapper class="com.kejizhentan.dao.IUserDao"/>-->
    </mappers>
</configuration>

⑷ 创建映射配置文件

IUserDao.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.kejizhentan.dao.IUserDao">
    <!--配置查询所有-->
    <select id = "findAll" resultType="com.kejizhentan.bean.User">
        select * from user
    </select>
      <!-- 根据id查询用户 -->
    <select id="findById" parameterType="int" resultType="com.kejizhentan.bean.User">
        select * from user where id = #{uid}
    </select>
     <!-- 根据名称模糊查询 -->
    <select id="findByName" parameterType="string" resultType="com.kejizhentan.bean.User">
          select * from user where username like #{name}
           <!--select * from user where username like '%${value}%'-->
          <!--select * from user where username like concat('%',#{name},'%')-->
    </select>
     <!--OGNL的介绍通过QueryVo查询user-->
        <select id="findUserByQueryVo" parameterType="com.kejizhentan.bean.QueryVo"  resultType="com.kejizhentan.bean.User">
                select * from user where id = #{user.userId}
        </select>

        <!-- 根据传入的参数条件来查询(查询条件不确定) -->
        <select id="findUserByCondition" parameterType="com.kejizhentan.bean.User" resultType="com.kejizhentan.bean.User">
              select * from user
              <where>
                <if test="username != null and username != '' ">
                     and username = #{username}
                </if>
              </where>
        </select>

       <!--根据id集合,查询用户信息-->
        <select id="findUserByIds" parameterType="java.util.List" resultType="com.kejizhentan.bean.User">
             select * from user
             <where>
               <if test="ids != null and ids.size() > 0">
                   <foreach collection="ids" open="and id in (" close=")" item="uid" separator=",">
                        #{uid}
                   </foreach>
               </if>
             </where>
       </select>
</mapper>

⑸ 测试类:

MybatisTest.java

public class MybatisTest {
    private InputStream is;
    private SqlSession sqlSession;
    private IUserDao userDao;
    /**
     * @Description 初始化加载资源的方法
     * @Author kejizhentan
     * @Date 2021/10/24 13:34
     **/
    @Before//用于在执行方法执行之前执行
    public void init(){
        try {
            //1.读取配置文件
            is = Resources.getResourceAsStream("SqlMapConfig.xml");
            //2.创建SqlSessionFactory工厂
            SqlSessionFactoryBuilder builder = new SqlSessionFactoryBuilder();
            SqlSessionFactory factory = builder.build(is);
            //3.使用工厂生产SqlSession对象
            sqlSession  = factory.openSession();
            //4.使用SqlSession创建Dao接口的代理对象
            userDao = sqlSession.getMapper(IUserDao.class);
        }catch (Exception e){
            e.printStackTrace();
        }
    }
    /**
     * @Description 释放资源的方法
     * @Author kejizhentan
     * @Date 2021/10/24 13:34
     **/
    @After//用于在测试方法执行之后执行
    public void close(){
        //提交事务
        sqlSession.commit();
        //6.释放资源
        if(sqlSession != null){
            sqlSession.close();
        }
        try {
            if(is != null){
                is.close();
            }
        }catch (Exception e){
            e.printStackTrace();
        }
    }
    /**
     * @Description 查询所有用户的操作
     * @Author kejizhentan
     * @Date 2021/10/24 13:51
     **/
    @Test
    public void findAll(){
            //5.使用代理对象执行方法
            List<User> users = userDao.findAll();
            for (User user : users) {
                System.out.println(user);
            }
    }
    /**
     * @Description 根据Id查询用户的方法
     * @Author kejizhentan
     * @Date 2021/10/24 13:52
     */
    @Test
    public void findById(){
        User user = userDao.findById(45);
        System.out.println(user);
    }
    /**
     * @Description 根据姓名模糊查询
     * @Author kejizhentan
     * @Date 2021/10/24 13:52
     */
    @Test
    public void findByName(){
        List<User> users = userDao.findByName("%王%");
        //List<User> users = userDao.findByName("王");
        for (User user : users) {
            System.out.println(user);
        }
    }

    /**
     * @Description 根据传入的参数条件来查询(查询条件不确定)
     * @Author kejizhentan
     * @Date 2021/10/30 21:51
     **/
    @Test
    public void findUserByCondition(){
        User user = new User();
        user.setUsername("老王");
        List<User> users = userDao.findUserByCondition(user);
        //List<User> users = userDao.findByName("王");
        for (User u : users) {
            System.out.println(u);
        }
    }

    /**
     * @Description 根据id集合,查询用户信息
     * @Author kejizhentan
     * @Date 2021/10/30 21:51
     **/
    @Test
    public void findUserByIds(){
        List<Integer> ids = new ArrayList();
        Collections.addAll(ids, 41, 42, 43);
        List<User> users = userDao.findUserByIds(ids);
        for (User u : users) {
            System.out.println(u);
        }
    }
}

补充:重复的sql可以抽取出来
在这里插入图片描述

十四、多表查询的操作

增加一张账户表的sql
DROP TABLE IF EXISTS account;
CREATE TABLE account (
ID int(11) NOT NULL COMMENT ‘编号’,
UID int(11) default NULL COMMENT ‘用户编号’,
MONEY double default NULL COMMENT ‘金额’,
PRIMARY KEY (ID),
KEY FK_Reference_8 (UID),
CONSTRAINT FK_Reference_8 FOREIGN KEY (UID) REFERENCES user (id)
) ENGINE=InnoDB DEFAULT CHARSET=utf8;
insert into account(ID,UID,MONEY) values (1,46,1000),(2,45,1000),(3,46,2000);

1. 一对一的多表查询操作

⑴ 主要配置

    <!--定义封装account和user的resultMap-->
    <resultMap id="accountUserMap" type="com.kejizhentan.bean.Account">
        <id property="id" column="aid"></id>
        <result property="uid" column="uid"></result>
        <result property="money" column="money"></result>
        <!--一对一的关系映射,配置封装user的内容-->
        <association property="user" column="uid" javaType="com.kejizhentan.bean.User">
            <id property="id" column="id"></id>
            <result property="username" column="username"></result>
            <result property="address" column="address"></result>
            <result property="sex" column="sex"></result>
            <result property="birthday" column="birthday"></result>
        </association>
    </resultMap>
    <!--配置查询所有-->
    <select id = "findAll" resultMap="accountUserMap">
        SELECT
          u.*,
          a.id    AS aid,
          a.uid,
          a.money
        FROM account a  LEFT JOIN USER u ON a.UID = u.id
    </select>
public class Account implements Serializable {

    private Integer id;
    private Integer uid;
    private Double money;
    //从表实体应该包含一个主表实体的对象引用
    private User user;
    ...
}

⑵ 详细代码

项目结构
在这里插入图片描述

⑴ 创建maven工程并导入坐标

<?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.kejizhentan</groupId>
    <artifactId>mybatis-project</artifactId>
    <version>1.0-SNAPSHOT</version>
    <packaging>jar</packaging>
    <dependencies>
        <!--Mybatis框架的依赖-->
        <dependency>
            <groupId>org.mybatis</groupId>
            <artifactId>mybatis</artifactId>
            <version>3.4.5</version>
        </dependency>
        <!--mysql数据库驱动的依赖-->
        <dependency>
            <groupId>mysql</groupId>
            <artifactId>mysql-connector-java</artifactId>
            <version>5.1.6</version>
        </dependency>
        <!--生成日志文件的依赖-->
        <dependency>
            <groupId>log4j</groupId>
            <artifactId>log4j</artifactId>
            <version>1.2.12</version>
        </dependency>
        <!--junit单元测试的依赖-->
        <dependency>
            <groupId>junit</groupId>
            <artifactId>junit</artifactId>
            <version>4.11</version>
            <scope>test</scope>
        </dependency>
    </dependencies>
</project>

⑵ 创建实体类和dao的接口

User.java

public class User implements Serializable {
    private Integer id;
    private String username;
    private Date birthday;
    private String sex;
    private String address;

    public Integer getId() {
        return id;
    }

    public void setId(Integer id) {
        this.id = id;
    }

    public String getUsername() {
        return username;
    }

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

    public Date getBirthday() {
        return birthday;
    }

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

    public String getSex() {
        return sex;
    }

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

    public String getAddress() {
        return address;
    }

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

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

Account.java

public class Account implements Serializable {

    private Integer id;
    private Integer uid;
    private Double money;

    //从表实体应该包含一个主表实体的对象引用
    private User user;

    public User getUser() {
        return user;
    }

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

    public Integer getId() {
        return id;
    }

    public void setId(Integer id) {
        this.id = id;
    }

    public Integer getUid() {
        return uid;
    }

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

    public Double getMoney() {
        return money;
    }

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

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

IAccountDao.java

public interface IAccountDao {
    /**
     * @Description 查询所有用户的方法
     * @Author kejizhentan
     * @Date 2021/10/24 12:51
     **/
    List<Account> findAll();

⑶ 创建Mybatis的主配置文件

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">
<!--Mybatis的主配置文件-->
<configuration>
    <!--配置环境-->
    <environments default="mysql">
        <!--配置mysql环境-->
        <environment id="mysql">
            <!--配置事务的类型-->
            <transactionManager type="JDBC"></transactionManager>
            <!--配置数据源(连接池)-->
            <dataSource type="POOLED">
                <!--配置数据的四个基本信息-->
                <property name="driver" value="com.mysql.jdbc.Driver"/>
                <property name="url" value="jdbc:mysql://localhost:3306/db4"/>
                <property name="username" value="root"/>
                <property name="password" value="root"/>
            </dataSource>
        </environment>
    </environments>
    <!--
     使用配置文件来实现mybatis的配置:
        指定映射配置文件的位置,映射配置文件指的是每个dao独立的配置文件
     使用注解来实现mybatis的配置:
        如果使用注解来配置的话,此处应该使用class属性指定被注解的dao全限制类名
    -->
    <mappers>
        <mapper resource="com/kejizhentan/dao/IAccountDao.xml"/>
        <!--<mapper class="com.kejizhentan.dao.IUserDao"/>-->
    </mappers>
</configuration

⑷ 创建映射配置文件

IAccountDao.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.kejizhentan.dao.IAccountDao">
    <!--定义封装account和user的resultMap-->
    <resultMap id="accountUserMap" type="com.kejizhentan.bean.Account">
        <id property="id" column="aid"></id>
        <result property="uid" column="uid"></result>
        <result property="money" column="money"></result>
        <!--一对一的关系映射,配置封装user的内容-->
        <association property="user" column="uid" javaType="com.kejizhentan.bean.User">
            <id property="id" column="id"></id>
            <result property="username" column="username"></result>
            <result property="address" column="address"></result>
            <result property="sex" column="sex"></result>
            <result property="birthday" column="birthday"></result>
        </association>
    </resultMap>
    <!--配置查询所有-->
    <select id = "findAll" resultMap="accountUserMap">
        SELECT
          u.*,
          a.id    AS aid,
          a.uid,
          a.money
        FROM account a  LEFT JOIN USER u ON a.UID = u.id
    </select>
</mapper>

⑸ 测试类:

MybatisTest.java

public class MybatisTest {
    private InputStream is;
    private SqlSession sqlSession;
    private IAccountDao accountDao;
    /**
     * @Description 初始化加载资源的方法
     * @Author kejizhentan
     * @Date 2021/10/24 13:34
     **/
    @Before//用于在执行方法执行之前执行
    public void init(){
        try {
            //1.读取配置文件
            is = Resources.getResourceAsStream("SqlMapConfig.xml");
            //2.创建SqlSessionFactory工厂
            SqlSessionFactoryBuilder builder = new SqlSessionFactoryBuilder();
            SqlSessionFactory factory = builder.build(is);
            //3.使用工厂生产SqlSession对象
            sqlSession  = factory.openSession();
            //4.使用SqlSession创建Dao接口的代理对象
            accountDao = sqlSession.getMapper(IAccountDao.class);
        }catch (Exception e){
            e.printStackTrace();
        }
    }
    /**
     * @Description 释放资源的方法
     * @Author kejizhentan
     * @Date 2021/10/24 13:34
     **/
    @After//用于在测试方法执行之后执行
    public void close(){
        //提交事务
        sqlSession.commit();
        //6.释放资源
        if(sqlSession != null){
            sqlSession.close();
        }
        try {
            if(is != null){
                is.close();
            }
        }catch (Exception e){
            e.printStackTrace();
        }
    }
    /**
     * @Description 查询所有用户的操作
     * @Author kejizhentan
     * @Date 2021/10/24 13:51
     **/
    @Test
    public void findAll(){
            //5.使用代理对象执行方法
            List<Account> accounts = accountDao.findAll();
            for (Account account : accounts) {
                System.out.println("----------------打印account信息--------------");
                System.out.println(account);
                System.out.println(account.getUser());
            }
    }
}

⑹ 结果如下:

在这里插入图片描述

注意:
在这里插入图片描述

2. 一对多的多表查询操作

⑴ 主要配置

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

⑵ 详细代码

项目结构:
在这里插入图片描述

⑴ 创建maven工程并导入坐标

<?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.kejizhentan</groupId>
    <artifactId>mybatis-project</artifactId>
    <version>1.0-SNAPSHOT</version>
    <packaging>jar</packaging>
    <dependencies>
        <!--Mybatis框架的依赖-->
        <dependency>
            <groupId>org.mybatis</groupId>
            <artifactId>mybatis</artifactId>
            <version>3.4.5</version>
        </dependency>
        <!--mysql数据库驱动的依赖-->
        <dependency>
            <groupId>mysql</groupId>
            <artifactId>mysql-connector-java</artifactId>
            <version>5.1.6</version>
        </dependency>
        <!--生成日志文件的依赖-->
        <dependency>
            <groupId>log4j</groupId>
            <artifactId>log4j</artifactId>
            <version>1.2.12</version>
        </dependency>
        <!--junit单元测试的依赖-->
        <dependency>
            <groupId>junit</groupId>
            <artifactId>junit</artifactId>
            <version>4.11</version>
            <scope>test</scope>
        </dependency>
    </dependencies>
</project>

⑵ 创建实体类和dao的接口

User.java

public class User implements Serializable {
    private Integer id;
    private String username;
    private Date birthday;
    private String sex;
    private String address;

    //一对多关系映射,主表实体应该包含从表实体的集合引用
    private List<Account> accounts;
    public List<Account> getAccounts() {
        return accounts;
    }
    public void setAccounts(List<Account> accounts) {
        this.accounts = accounts;
    }

    public Integer getId() {
        return id;
    }

    public void setId(Integer id) {
        this.id = id;
    }

    public String getUsername() {
        return username;
    }

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

    public Date getBirthday() {
        return birthday;
    }

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

    public String getSex() {
        return sex;
    }

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

    public String getAddress() {
        return address;
    }

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

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

Account.java

public class Account implements Serializable {

    private Integer id;
    private Integer uid;
    private Double money;

    public Integer getId() {
        return id;
    }

    public void setId(Integer id) {
        this.id = id;
    }

    public Integer getUid() {
        return uid;
    }

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

    public Double getMoney() {
        return money;
    }

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

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

IUserDao.java

public interface IUserDao {
    /**
     * @Description 查询所有用户的方法
     * @Author kejizhentan
     * @Date 2021/10/24 12:51
     **/
    List<User> findAll();
}

⑶ 创建Mybatis的主配置文件

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">
<!--Mybatis的主配置文件-->
<configuration>
    <!--配置环境-->
    <environments default="mysql">
        <!--配置mysql环境-->
        <environment id="mysql">
            <!--配置事务的类型-->
            <transactionManager type="JDBC"></transactionManager>
            <!--配置数据源(连接池)-->
            <dataSource type="POOLED">
                <!--配置数据的四个基本信息-->
                <property name="driver" value="com.mysql.jdbc.Driver"/>
                <property name="url" value="jdbc:mysql://localhost:3306/db4"/>
                <property name="username" value="root"/>
                <property name="password" value="root"/>
            </dataSource>
        </environment>
    </environments>
    <!--
     使用配置文件来实现mybatis的配置:
        指定映射配置文件的位置,映射配置文件指的是每个dao独立的配置文件
     使用注解来实现mybatis的配置:
        如果使用注解来配置的话,此处应该使用class属性指定被注解的dao全限制类名
    -->
    <mappers>
        <!--<mapper resource="com/kejizhentan/dao/IAccountDao.xml"/>-->
        <!--<mapper class="com.kejizhentan.dao.IUserDao"/>-->
        <package name="com.kejizhentan.dao"/>
    </mappers>
</configuration>

⑷ 创建映射配置文件

IUserDao.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.kejizhentan.dao.IUserDao">
   <!-- 定义User的resultMap-->
       <resultMap id="userAccountMap" type="com.kejizhentan.bean.User">
           <id property="id" column="id"></id>
           <result property="username" column="username"></result>
           <result property="address" column="address"></result>
           <result property="sex" column="sex"></result>
           <result property="birthday" column="birthday"></result>
           <!-- 配置user对象中accounts集合的映射 -->
           <collection property="accounts" ofType="com.kejizhentan.bean.Account">
               <id column="aid" property="id"></id>
               <result column="uid" property="uid"></result>
               <result column="money" property="money"></result>
           </collection>
       </resultMap>
    <!--配置查询所有-->
    <select id = "findAll" resultMap="userAccountMap">
        select * from user u left join account a on u.id = a.uid
    </select>
</mapper>

⑸ 测试类:

MybatisTest.java

public class MybatisTest {
    private InputStream is;
    private SqlSession sqlSession;
    private IUserDao userDao;
    /**
     * @Description 初始化加载资源的方法
     * @Author kejizhentan
     * @Date 2021/10/24 13:34
     **/
    @Before//用于在执行方法执行之前执行
    public void init(){
        try {
            //1.读取配置文件
            is = Resources.getResourceAsStream("SqlMapConfig.xml");
            //2.创建SqlSessionFactory工厂
            SqlSessionFactoryBuilder builder = new SqlSessionFactoryBuilder();
            SqlSessionFactory factory = builder.build(is);
            //3.使用工厂生产SqlSession对象
            sqlSession  = factory.openSession();
            //4.使用SqlSession创建Dao接口的代理对象
            userDao = sqlSession.getMapper(IUserDao.class);
        }catch (Exception e){
            e.printStackTrace();
        }
    }
    /**
     * @Description 释放资源的方法
     * @Author kejizhentan
     * @Date 2021/10/24 13:34
     **/
    @After//用于在测试方法执行之后执行
    public void close(){
        //提交事务
        sqlSession.commit();
        //6.释放资源
        if(sqlSession != null){
            sqlSession.close();
        }
        try {
            if(is != null){
                is.close();
            }
        }catch (Exception e){
            e.printStackTrace();
        }
    }
    /**
     * @Description 查询所有用户的操作
     * @Author kejizhentan
     * @Date 2021/10/24 13:51
     **/
    @Test
    public void findAll(){
            //5.使用代理对象执行方法
            List<User> users = userDao.findAll();
            for (User user : users) {
                System.out.println("----------------打印account信息--------------");
                System.out.println(user);
                System.out.println(user.getAccounts());
            }
    }
}

⑹ 结果如下:

在这里插入图片描述

3. 多对多的多表查询操作

增加两张表
DROP TABLE IF EXISTS role;

CREATE TABLE role ( ID int(11) NOT NULL COMMENT ‘编号’,
ROLE_NAME varchar(30) default NULL COMMENT ‘角色名称’, ROLE_DESC
varchar(60) default NULL COMMENT ‘角色描述’, PRIMARY KEY (ID) )
ENGINE=InnoDB DEFAULT CHARSET=utf8; insert into
role(ID,ROLE_NAME,ROLE_DESC) values
(1,‘院长’,‘管理整个学院’),(2,‘总裁’,‘管理整个公司’),(3,‘校长’,‘管理整个学校’); DROP TABLE IF
EXISTS user_role; CREATE TABLE user_role ( UID int(11) NOT
NULL COMMENT ‘用户编号’, RID int(11) NOT NULL COMMENT ‘角色编号’,
PRIMARY KEY (UID,RID), KEY FK_Reference_10 (RID),
CONSTRAINT FK_Reference_10 FOREIGN KEY (RID) REFERENCES role
(ID), CONSTRAINT FK_Reference_9 FOREIGN KEY (UID) REFERENCES
user (id) ) ENGINE=InnoDB DEFAULT CHARSET=utf8; insert into
user_role(UID,RID) values (41,1),(45,1),(41,2);

⑴ 主要配置

public class Role implements Serializable {

    private Integer roleId;
    private String roleName;
    private String roleDesc;

    //多对多的关系映射:一个角色可以赋予多个用户
    private List<User> users;
    . . . 
}
<?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.kejizhentan.dao.IRoleDao">

    <!--定义role表的ResultMap-->
    <resultMap id="roleMap" type="com.kejizhentan.bean.Role">
        <id property="roleId" column="rid"></id>
        <result property="roleName" column="role_name"></result>
        <result property="roleDesc" column="role_desc"></result>
        <collection property="users" ofType="com.kejizhentan.bean.User">
            <id column="id" property="id"></id>
            <result column="username" property="username"></result>
            <result column="address" property="address"></result>
            <result column="sex" property="sex"></result>
            <result column="birthday" property="birthday"></result>
        </collection>
    </resultMap>

    <!--查询所有-->
    <select id="findAll" resultMap="roleMap">
       select u.*,r.id as rid,r.role_name,r.role_desc from role r
        left outer join user_role ur  on r.id = ur.rid
        left outer join user u on u.id = ur.uid
    </select>
</mapper>

⑵ 详细代码

项目结构:
在这里插入图片描述

⑴ 创建maven工程并导入坐标

<?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.kejizhentan</groupId>
    <artifactId>mybatis-project</artifactId>
    <version>1.0-SNAPSHOT</version>
    <packaging>jar</packaging>
    <dependencies>
        <!--Mybatis框架的依赖-->
        <dependency>
            <groupId>org.mybatis</groupId>
            <artifactId>mybatis</artifactId>
            <version>3.4.5</version>
        </dependency>
        <!--mysql数据库驱动的依赖-->
        <dependency>
            <groupId>mysql</groupId>
            <artifactId>mysql-connector-java</artifactId>
            <version>5.1.6</version>
        </dependency>
        <!--生成日志文件的依赖-->
        <dependency>
            <groupId>log4j</groupId>
            <artifactId>log4j</artifactId>
            <version>1.2.12</version>
        </dependency>
        <!--junit单元测试的依赖-->
        <dependency>
            <groupId>junit</groupId>
            <artifactId>junit</artifactId>
            <version>4.11</version>
            <scope>test</scope>
        </dependency>
    </dependencies>
</project>

⑵ 创建实体类和dao的接口

User.java

public class User implements Serializable {
    private Integer id;
    private String username;
    private Date birthday;
    private String sex;
    private String address;
    public Integer getId() {
        return id;
    }

    public void setId(Integer id) {
        this.id = id;
    }

    public String getUsername() {
        return username;
    }

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

    public Date getBirthday() {
        return birthday;
    }

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

    public String getSex() {
        return sex;
    }

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

    public String getAddress() {
        return address;
    }

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

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

Role.java

public class Role implements Serializable {

    private Integer roleId;
    private String roleName;
    private String roleDesc;

    //多对多的关系映射:一个角色可以赋予多个用户
    private List<User> users;

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

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

    public Integer getRoleId() {
        return roleId;
    }

    public void setRoleId(Integer roleId) {
        this.roleId = roleId;
    }

    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{" +
                "roleId=" + roleId +
                ", roleName='" + roleName + '\'' +
                ", roleDesc='" + roleDesc + '\'' +
                '}';
    }
}

IRoleDao.java

public interface IRoleDao {
    /**
     * 查询所有角色
     * @return
     */
    List<Role> findAll();
}

⑶ 创建Mybatis的主配置文件

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">
<!--Mybatis的主配置文件-->
<configuration>
    <!--配置环境-->
    <environments default="mysql">
        <!--配置mysql环境-->
        <environment id="mysql">
            <!--配置事务的类型-->
            <transactionManager type="JDBC"></transactionManager>
            <!--配置数据源(连接池)-->
            <dataSource type="POOLED">
                <!--配置数据的四个基本信息-->
                <property name="driver" value="com.mysql.jdbc.Driver"/>
                <property name="url" value="jdbc:mysql://localhost:3306/db4"/>
                <property name="username" value="root"/>
                <property name="password" value="root"/>
            </dataSource>
        </environment>
    </environments>
    <!--
     使用配置文件来实现mybatis的配置:
        指定映射配置文件的位置,映射配置文件指的是每个dao独立的配置文件
     使用注解来实现mybatis的配置:
        如果使用注解来配置的话,此处应该使用class属性指定被注解的dao全限制类名
    -->
    <mappers>
        <!--<mapper resource="com/kejizhentan/dao/IAccountDao.xml"/>-->
        <!--<mapper class="com.kejizhentan.dao.IUserDao"/>-->
        <package name="com.kejizhentan.dao"/>
    </mappers>
</configuration>

⑷ 创建映射配置文件

IRoleDao.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.kejizhentan.dao.IRoleDao">

    <!--定义role表的ResultMap-->
    <resultMap id="roleMap" type="com.kejizhentan.bean.Role">
        <id property="roleId" column="rid"></id>
        <result property="roleName" column="role_name"></result>
        <result property="roleDesc" column="role_desc"></result>
        <collection property="users" ofType="com.kejizhentan.bean.User">
            <id column="id" property="id"></id>
            <result column="username" property="username"></result>
            <result column="address" property="address"></result>
            <result column="sex" property="sex"></result>
            <result column="birthday" property="birthday"></result>
        </collection>
    </resultMap>

    <!--查询所有-->
    <select id="findAll" resultMap="roleMap">
       select u.*,r.id as rid,r.role_name,r.role_desc from role r
        left outer join user_role ur  on r.id = ur.rid
        left outer join user u on u.id = ur.uid
    </select>
</mapper>

⑸ 测试类:

MybatisTest.java

/**
 *@Description mybatis的CRUD测试类
 *@Author kejizhentan
 *@Date 2021/10/24 14:37
 */
public class MybatisTest {
    private InputStream is;
    private SqlSession sqlSession;
    private IRoleDao roleDao;
    /**
     * @Description 初始化加载资源的方法
     * @Author kejizhentan
     * @Date 2021/10/24 13:34
     **/
    @Before//用于在执行方法执行之前执行
    public void init(){
        try {
            //1.读取配置文件
            is = Resources.getResourceAsStream("SqlMapConfig.xml");
            //2.创建SqlSessionFactory工厂
            SqlSessionFactoryBuilder builder = new SqlSessionFactoryBuilder();
            SqlSessionFactory factory = builder.build(is);
            //3.使用工厂生产SqlSession对象
            sqlSession  = factory.openSession();
            //4.使用SqlSession创建Dao接口的代理对象
            roleDao = sqlSession.getMapper(IRoleDao.class);
        }catch (Exception e){
            e.printStackTrace();
        }
    }
    /**
     * @Description 释放资源的方法
     * @Author kejizhentan
     * @Date 2021/10/24 13:34
     **/
    @After//用于在测试方法执行之后执行
    public void close(){
        //提交事务
        sqlSession.commit();
        //6.释放资源
        if(sqlSession != null){
            sqlSession.close();
        }
        try {
            if(is != null){
                is.close();
            }
        }catch (Exception e){
            e.printStackTrace();
        }
    }
    /**
     * @Description 查询所有用户的操作
     * @Author kejizhentan
     * @Date 2021/10/24 13:51
     **/
    @Test
    public void findAll(){
            //5.使用代理对象执行方法
            List<Role> roles = roleDao.findAll();
            for (Role role : roles) {
                System.out.println("----------------打印role信息--------------");
                System.out.println(role);
                System.out.println(role.getUsers());
            }
    }
}

⑹ 结果如下:

在这里插入图片描述

十五、 Mybatis中的延迟加载

1. 什么是延迟加载

在真正使用数据时才发起查询,不用的时候不查询。按需加载(懒加载)

2. 什么是立即加载

不管用不用,只要一调用方法,马上发起查询。

3. 在对应的四种表关系中:

一对多,多对多通常情况下我们都是采用延迟加载。
多对一,一对一通常情况下我们都是采用立即加载。

4.延迟加载场景演示

⑴ 一对一多表查询懒加载演示

① 主要配置
  • IAccountDao.xml中的配置

    <resultMap id="accountUserMap" type="com.kejizhentan.bean.Account">
           .	.	.
     <association property="user" column="uid" javaType="com.kejizhentan.bean.User" select="com.kejizhentan.dao.IUserDao.findById"></association>
    </resultMap>
    
  • SqlMapConfig.xml中的配置

    <!--配置参数-->
        <settings>
            <!--开启Mybatis支持延迟加载的开关-->
            <setting name="lazyLoadingEnabled" value="true"/>
            <!--将积极加载改为按需加载 mybatis3.4.1以后默认是false的,可以不用设置-->
            <setting name="aggressiveLazyLoading" value="false"></setting>
        </settings>
    
② 详细代码
  • 项目结构
    在这里插入图片描述

  • 创建maven工程并导入坐标

    <?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.kejizhentan</groupId>
        <artifactId>mybatis-project</artifactId>
        <version>1.0-SNAPSHOT</version>
        <packaging>jar</packaging>
        <dependencies>
            <!--Mybatis框架的依赖-->
            <dependency>
                <groupId>org.mybatis</groupId>
                <artifactId>mybatis</artifactId>
                <version>3.4.5</version>
            </dependency>
            <!--mysql数据库驱动的依赖-->
            <dependency>
                <groupId>mysql</groupId>
                <artifactId>mysql-connector-java</artifactId>
                <version>5.1.6</version>
            </dependency>
            <!--生成日志文件的依赖-->
            <dependency>
                <groupId>log4j</groupId>
                <artifactId>log4j</artifactId>
                <version>1.2.12</version>
            </dependency>
            <!--junit单元测试的依赖-->
            <dependency>
                <groupId>junit</groupId>
                <artifactId>junit</artifactId>
                <version>4.11</version>
                <scope>test</scope>
            </dependency>
        </dependencies>
    </project>
    
  • 创建实体类和dao的接口
    User.java

    public class User implements Serializable {
        private Integer id;
        private String username;
        private Date birthday;
        private String sex;
        private String address;
    
        public Integer getId() {
            return id;
        }
    
        public void setId(Integer id) {
            this.id = id;
        }
    
        public String getUsername() {
            return username;
        }
    
        public void setUsername(String username) {
            this.username = username;
        }
    
        public Date getBirthday() {
            return birthday;
        }
    
        public void setBirthday(Date birthday) {
            this.birthday = birthday;
        }
    
        public String getSex() {
            return sex;
        }
    
        public void setSex(String sex) {
            this.sex = sex;
        }
    
        public String getAddress() {
            return address;
        }
    
        public void setAddress(String address) {
            this.address = address;
        }
    
        @Override
        public String toString() {
            return "User{" +
                    "id=" + id +
                    ", username='" + username + '\'' +
                    ", birthday=" + birthday +
                    ", sex='" + sex + '\'' +
                    ", address='" + address + '\'' +
                    '}';
        }
    }
    

    Account.java

    public class Account implements Serializable {
    
        private Integer id;
        private Integer uid;
        private Double money;
        public Integer getId() {
            return id;
        }
        //一对多关系映射,主表实体应该包含子表实体的集合
        private User user;
    
        public User getUser() {
            return user;
        }
    
        public void setUser(User user) {
            this.user = user;
        }
    
        public void setId(Integer id) {
            this.id = id;
        }
    
        public Integer getUid() {
            return uid;
        }
    
        public void setUid(Integer uid) {
            this.uid = uid;
        }
    
        public Double getMoney() {
            return money;
        }
    
        public void setMoney(Double money) {
            this.money = money;
        }
    
        @Override
        public String toString() {
            return "Account{" +
                    "id=" + id +
                    ", uid=" + uid +
                    ", money=" + money +
                    '}';
        }
    }
    

    IUserDao.java

    public interface IUserDao {
        /**
         * @Description 查询所有用户的方法
         * @Author kejizhentan
         * @Date 2021/10/24 12:51
         **/
        User findById(Integer id);
    }
    

    IAccountDao.java

    public interface IAccountDao {
        /**
         * @Description 查询所有用户的方法
         * @Author kejizhentan
         * @Date 2021/10/24 12:51
         **/
        List<Account> findAll();
    }
    
  • 创建Mybatis的主配置文件
    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">
    <!--Mybatis的主配置文件-->
    <configuration>
        <!--延迟加载参数配置-->
        <!--配置参数-->
        <settings>
            <!--开启Mybatis支持延迟加载的开关-->
            <setting name="lazyLoadingEnabled" value="true"/>
            <!--将积极加载改为按需加载 mybatis3.4.1以后默认是开启的,可以不用设置-->
            <setting name="aggressiveLazyLoading" value="false"></setting>
        </settings>
        <!--配置环境-->
        <environments default="mysql">
            <!--配置mysql环境-->
            <environment id="mysql">
                <!--配置事务的类型-->
                <transactionManager type="JDBC"></transactionManager>
                <!--配置数据源(连接池)-->
                <dataSource type="POOLED">
                    <!--配置数据的四个基本信息-->
                    <property name="driver" value="com.mysql.jdbc.Driver"/>
                    <property name="url" value="jdbc:mysql://localhost:3306/db4"/>
                    <property name="username" value="root"/>
                    <property name="password" value="root"/>
                </dataSource>
            </environment>
        </environments>
        <!--
         使用配置文件来实现mybatis的配置:
            指定映射配置文件的位置,映射配置文件指的是每个dao独立的配置文件
         使用注解来实现mybatis的配置:
            如果使用注解来配置的话,此处应该使用class属性指定被注解的dao全限制类名
        -->
        <mappers>
            <!--<mapper resource="com/kejizhentan/dao/IAccountDao.xml"/>-->
            <!--<mapper class="com.kejizhentan.dao.IUserDao"/>-->
            <package name="com.kejizhentan.dao"/>
        </mappers>
    </configuration>
    
  • 创建映射配置文件
    IUserDao.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.kejizhentan.dao.IUserDao">
        <select id = "findById" parameterType="java.lang.Integer"  resultType="com.kejizhentan.bean.User">
            select * from user u where id  = #{id}
        </select>
    </mapper>
    

    IAccountDao.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.kejizhentan.dao.IAccountDao">
        <!--定义封装account和user的resultMap-->
        <resultMap id="accountUserMap" type="com.kejizhentan.bean.Account">
            <id property="id" column="aid"></id>
            <result property="uid" column="uid"></result>
            <result property="money" column="money"></result>
            <!--一对一的关系映射,配置封装user的内容
                select属性指定的内容,查询用户的唯一标识
                column属性指定的内容:用户根据id查询时,所需要的参数值
            -->
            <association property="user" column="uid" javaType="com.kejizhentan.bean.User" select="com.kejizhentan.dao.IUserDao.findById"></association>
        </resultMap>
        <!--配置查询所有-->
        <select id = "findAll" resultMap="accountUserMap">
            SELECT
             *
            FROM account a
        </select>
    </mapper>
    
  • 测试类:
    MybatisTest.java

    public class MybatisTest {
        private InputStream is;
        private SqlSession sqlSession; 
        private IAccountDao accountDao;
    
        /**
         * @Description 初始化加载资源的方法
         * @Author kejizhentan
         * @Date 2021/10/24 13:34
         **/
        @Before//用于在执行方法执行之前执行
        public void init() {
            try {
                //1.读取配置文件
                is = Resources.getResourceAsStream("SqlMapConfig.xml");
                //2.创建SqlSessionFactory工厂
                SqlSessionFactoryBuilder builder = new SqlSessionFactoryBuilder();
                SqlSessionFactory factory = builder.build(is);
                //3.使用工厂生产SqlSession对象
                sqlSession = factory.openSession();
                //4.使用SqlSession创建Dao接口的代理对象
                accountDao = sqlSession.getMapper(IAccountDao.class);
            } catch (Exception e) {
                e.printStackTrace();
            }
        }
    
        /**
         * @Description 释放资源的方法
         * @Author kejizhentan
         * @Date 2021/10/24 13:34
         **/
        @After//用于在测试方法执行之后执行
        public void close() {
            //提交事务
            sqlSession.commit();
            //6.释放资源
            if (sqlSession != null) {
                sqlSession.close();
            }
            try {
                if (is != null) {
                    is.close();
                }
            } catch (Exception e) {
                e.printStackTrace();
            }
        }
    
        /**
         * @Description 查询所有账户
         * @Author kejizhentan
         * @Date 2021/11/6 12:00
         **/
        @Test
        public void findAll() {
            //5.使用代理对象执行方法
            List<Account> accounts = accountDao.findAll();
            for (Account account : accounts) {
                System.out.println("----------------打印account信息--------------");
                System.out.println(account);
               System.out.println(account.getUser());
            }
        }
    }
    
  • 结果如下:
    在这里插入图片描述

注意:一对一普通查询和懒加载查询sql对比
普通查询在这里插入图片描述
懒加载在这里插入图片描述

⑵ 一对多查询懒加载演示

① 主要配置
  • IUserDao.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.kejizhentan.dao.IUserDao">
         <!-- 定义User的resultMap-->
           <resultMap id="userAccountMap" type="com.kejizhentan.bean.User">
               <id property="id" column="id"></id>
               <result property="username" column="username"></result>
               <result property="address" column="address"></result>
               <result property="sex" column="sex"></result>
               <result property="birthday" column="birthday"></result>
               <!-- 配置user对象中accounts集合的映射,注意,这地方的column应该是id,应为使用的是用户的id -->
               <collection property="accounts" ofType="com.kejizhentan.bean.Account" select="com.kejizhentan.dao.IUserDao.findByUId" column="id"></collection>
           </resultMap>
        <select id = "findAll"   resultMap="userAccountMap">
            select * from user u
        </select>
    
        <!--根据用户id查询账户信息-->
        <select id = "findByUId"  resultType="com.kejizhentan.bean.Account">
            select * from account a where a.uid  = #{uid}
        </select>
    </mapper>
    
  • SqlMapConfig.xml中的配置

    <!--配置参数-->
        <settings>
            <!--开启Mybatis支持延迟加载的开关-->
            <setting name="lazyLoadingEnabled" value="true"/>
            <!--将积极加载改为按需加载 mybatis3.4.1以后默认是false的,可以不用设置-->
            <setting name="aggressiveLazyLoading" value="false"></setting>
        </settings>
    
② 详细代码
  • 项目结构
    在这里插入图片描述

  • 创建maven工程并导入坐标

    <?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.kejizhentan</groupId>
        <artifactId>mybatis-project</artifactId>
        <version>1.0-SNAPSHOT</version>
        <packaging>jar</packaging>
        <dependencies>
            <!--Mybatis框架的依赖-->
            <dependency>
                <groupId>org.mybatis</groupId>
                <artifactId>mybatis</artifactId>
                <version>3.4.5</version>
            </dependency>
            <!--mysql数据库驱动的依赖-->
            <dependency>
                <groupId>mysql</groupId>
                <artifactId>mysql-connector-java</artifactId>
                <version>5.1.6</version>
            </dependency>
            <!--生成日志文件的依赖-->
            <dependency>
                <groupId>log4j</groupId>
                <artifactId>log4j</artifactId>
                <version>1.2.12</version>
            </dependency>
            <!--junit单元测试的依赖-->
            <dependency>
                <groupId>junit</groupId>
                <artifactId>junit</artifactId>
                <version>4.11</version>
                <scope>test</scope>
            </dependency>
        </dependencies>
    </project>
    
  • 创建实体类和dao的接口
    User.java

    public class User implements Serializable {
    private Integer id;
    private String username;
    private Date birthday;
    private String sex;
    private String address;
    
    //一对多关系映射,主表实体应该包含从表实体的集合引用
    private List<Account> accounts;
    public List<Account> getAccounts() {
        return accounts;
    }
    public void setAccounts(List<Account> accounts) {
        this.accounts = accounts;
    }
    
    public Integer getId() {
        return id;
    }
    
    public void setId(Integer id) {
        this.id = id;
    }
    
    public String getUsername() {
        return username;
    }
    
    public void setUsername(String username) {
        this.username = username;
    }
    
    public Date getBirthday() {
        return birthday;
    }
    
    public void setBirthday(Date birthday) {
        this.birthday = birthday;
    }
    
    public String getSex() {
        return sex;
    }
    
    public void setSex(String sex) {
        this.sex = sex;
    }
    
    public String getAddress() {
        return address;
    }
    
    public void setAddress(String address) {
        this.address = address;
    }
    
    @Override
    public String toString() {
        return "User{" +
                "id=" + id +
                ", username='" + username + '\'' +
                ", birthday=" + birthday +
                ", sex='" + sex + '\'' +
                ", address='" + address + '\'' +
                '}';
        }
    }
    

    Account.java

    public class Account implements Serializable {
    
    private Integer id;
    private Integer uid;
    private Double money;
    public Integer getId() {
        return id;
    }
    
    public void setId(Integer id) {
        this.id = id;
    }
    
    public Integer getUid() {
        return uid;
    }
    
    public void setUid(Integer uid) {
        this.uid = uid;
    }
    
    public Double getMoney() {
        return money;
    }
    
    public void setMoney(Double money) {
        this.money = money;
    }
    
    @Override
    public String toString() {
        return "Account{" +
                "id=" + id +
                ", uid=" + uid +
                ", money=" + money +
                '}';
        }
    }
    

    IUserDao.java

    public interface IUserDao {
    /**
     * @Description 查询所有用户的方法
     * @Author kejizhentan
     * @Date 2021/10/24 12:51
     **/
    List<User> findAll();
    
    /**
     * @Description 根据用户id查询账户信息
     * @Author kejizhentan
     * @Date 2021/10/24 12:51
     **/
    List<Account> findByUId(Integer uid);
    }
    
  • 创建Mybatis的主配置文件
    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">
    <!--Mybatis的主配置文件-->
    <configuration>
        <!--延迟加载参数配置-->
        <!--配置参数-->
        <settings>
            <!--开启Mybatis支持延迟加载的开关-->
            <setting name="lazyLoadingEnabled" value="true"/>
            <!--将积极加载改为按需加载 mybatis3.4.1以后默认是开启的,可以不用设置-->
            <setting name="aggressiveLazyLoading" value="false"></setting>
        </settings>
        <!--配置环境-->
        <environments default="mysql">
            <!--配置mysql环境-->
            <environment id="mysql">
                <!--配置事务的类型-->
                <transactionManager type="JDBC"></transactionManager>
                <!--配置数据源(连接池)-->
                <dataSource type="POOLED">
                    <!--配置数据的四个基本信息-->
                    <property name="driver" value="com.mysql.jdbc.Driver"/>
                    <property name="url" value="jdbc:mysql://localhost:3306/db4"/>
                    <property name="username" value="root"/>
                    <property name="password" value="root"/>
                </dataSource>
            </environment>
        </environments>
        <!--
         使用配置文件来实现mybatis的配置:
            指定映射配置文件的位置,映射配置文件指的是每个dao独立的配置文件
         使用注解来实现mybatis的配置:
            如果使用注解来配置的话,此处应该使用class属性指定被注解的dao全限制类名
        -->
        <mappers>
            <!--<mapper resource="com/kejizhentan/dao/IAccountDao.xml"/>-->
            <!--<mapper class="com.kejizhentan.dao.IUserDao"/>-->
            <package name="com.kejizhentan.dao"/>
        </mappers>
    </configuration>
    
  • 创建映射配置文件
    IUserDao.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.kejizhentan.dao.IUserDao">
         <!-- 定义User的resultMap-->
           <resultMap id="userAccountMap" type="com.kejizhentan.bean.User">
               <id property="id" column="id"></id>
               <result property="username" column="username"></result>
               <result property="address" column="address"></result>
               <result property="sex" column="sex"></result>
               <result property="birthday" column="birthday"></result>
               <!-- 配置user对象中accounts集合的映射,注意,这地方的column应该是id,应为使用的是用户的id -->
               <collection property="accounts" ofType="com.kejizhentan.bean.Account" select="com.kejizhentan.dao.IUserDao.findByUId" column="id"></collection>
           </resultMap>
        <select id = "findAll"   resultMap="userAccountMap">
            select * from user u
        </select>
    
        <!--根据用户id查询账户信息-->
        <select id = "findByUId"  resultType="com.kejizhentan.bean.Account">
            select * from account a where a.uid  = #{uid}
        </select>
    </mapper>
    
  • 测试类:
    MybatisTest.java

    public class MybatisTest {
        private InputStream is;
        private SqlSession sqlSession;
        private IUserDao userDao;
    
        /**
         * @Description 初始化加载资源的方法
         * @Author kejizhentan
         * @Date 2021/10/24 13:34
         **/
        @Before//用于在执行方法执行之前执行
        public void init() {
            try {
                //1.读取配置文件
                is = Resources.getResourceAsStream("SqlMapConfig.xml");
                //2.创建SqlSessionFactory工厂
                SqlSessionFactoryBuilder builder = new SqlSessionFactoryBuilder();
                SqlSessionFactory factory = builder.build(is);
                //3.使用工厂生产SqlSession对象
                sqlSession = factory.openSession();
                //4.使用SqlSession创建Dao接口的代理对象
                userDao = sqlSession.getMapper(IUserDao.class);
            } catch (Exception e) {
                e.printStackTrace();
            }
        }
    
        /**
         * @Description 释放资源的方法
         * @Author kejizhentan
         * @Date 2021/10/24 13:34
         **/
        @After//用于在测试方法执行之后执行
        public void close() {
            //提交事务
            sqlSession.commit();
            //6.释放资源
            if (sqlSession != null) {
                sqlSession.close();
            }
            try {
                if (is != null) {
                    is.close();
                }
            } catch (Exception e) {
                e.printStackTrace();
            }
        }
    
        /**
         * @Description 查询所有账户
         * @Author kejizhentan
         * @Date 2021/11/6 12:00
         **/
        @Test
        public void findAll() {
            //5.使用代理对象执行方法
            List<User> users = userDao.findAll();
            for (User user : users) {
                System.out.println(user);
                System.out.println(user.getAccounts());
            }
        }
    
    }
    
  • 结果如下:
    在这里插入图片描述

十六、Mybatis中的缓存

1. 什么是缓存

存在于内存中的临时数据。

2. 为什么使用缓存

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

3. 什么样的数据能使用缓存,什么样的数据不能使用

  • 适用于缓存:
    经常查询并且不经常改变的。
    数据的正确与否对最终结果影响不大的。
  • 不适用于缓存:
    经常改变的数据
    数据的正确与否对最终结果影响很大的。
    例如:商品的库存,银行的汇率,股市的牌价。

4. Mybatis中的一级缓存和二级缓存

⑴ 一级缓存:

它指的是Mybatis中SqlSession对象的缓存。当我们执行查询之后,查询的结果会同时存入到SqlSession为我们提供一块区域中。该区域的结构是一个Map。当我们再次查询同样的数据,mybatis会先去sqlsession中查询是否有,有的话直接拿出来用。当SqlSession对象消失时,mybatis的一级缓存也就消失了。

① 一级缓存的使用
  • mybatis一级缓存默认是开启的。
  • mybatis一级缓存失效的方式有两种
    方式一:关闭sqlSession
    方式二:使用clearCache方法清理缓存
详细代码
  • 项目结构
    在这里插入图片描述

  • 创建maven工程并导入坐标

    <?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.kejizhentan</groupId>
        <artifactId>mybatis-project</artifactId>
        <version>1.0-SNAPSHOT</version>
        <packaging>jar</packaging>
        <dependencies>
            <!--Mybatis框架的依赖-->
            <dependency>
                <groupId>org.mybatis</groupId>
                <artifactId>mybatis</artifactId>
                <version>3.4.5</version>
            </dependency>
            <!--mysql数据库驱动的依赖-->
            <dependency>
                <groupId>mysql</groupId>
                <artifactId>mysql-connector-java</artifactId>
                <version>5.1.6</version>
            </dependency>
            <!--生成日志文件的依赖-->
            <dependency>
                <groupId>log4j</groupId>
                <artifactId>log4j</artifactId>
                <version>1.2.12</version>
            </dependency>
            <!--junit单元测试的依赖-->
            <dependency>
                <groupId>junit</groupId>
                <artifactId>junit</artifactId>
                <version>4.11</version>
                <scope>test</scope>
            </dependency>
        </dependencies>
    </project>
    
  • 创建实体类和dao的接口
    User.java

    public class User implements Serializable {
    private Integer id;
    private String username;
    private Date birthday;
    private String sex;
    private String address;
    
    public Integer getId() {
        return id;
    }
    
    public void setId(Integer id) {
        this.id = id;
    }
    
    public String getUsername() {
        return username;
    }
    
    public void setUsername(String username) {
        this.username = username;
    }
    
    public Date getBirthday() {
        return birthday;
    }
    
    public void setBirthday(Date birthday) {
        this.birthday = birthday;
    }
    
    public String getSex() {
        return sex;
    }
    
    public void setSex(String sex) {
        this.sex = sex;
    }
    
    public String getAddress() {
        return address;
    }
    
    public void setAddress(String address) {
        this.address = address;
    }
    
    }
    

    IUserDao.java

    public interface IUserDao {
    /**
     * @Description 查询所有用户的方法
     * @Author kejizhentan
     * @Date 2021/10/24 12:51
     **/
    User findById(Integer id);
    }
    
  • 创建Mybatis的主配置文件
    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">
    <!--Mybatis的主配置文件-->
    <configuration>
        <!--配置环境-->
        <environments default="mysql">
            <!--配置mysql环境-->
            <environment id="mysql">
                <!--配置事务的类型-->
                <transactionManager type="JDBC"></transactionManager>
                <!--配置数据源(连接池)-->
                <dataSource type="POOLED">
                    <!--配置数据的四个基本信息-->
                    <property name="driver" value="com.mysql.jdbc.Driver"/>
                    <property name="url" value="jdbc:mysql://localhost:3306/db4"/>
                    <property name="username" value="root"/>
                    <property name="password" value="root"/>
                </dataSource>
            </environment>
        </environments>
        <!--
         使用配置文件来实现mybatis的配置:
            指定映射配置文件的位置,映射配置文件指的是每个dao独立的配置文件
         使用注解来实现mybatis的配置:
            如果使用注解来配置的话,此处应该使用class属性指定被注解的dao全限制类名
        -->
        <mappers>
            <!--<mapper resource="com/kejizhentan/dao/IAccountDao.xml"/>-->
            <!--<mapper class="com.kejizhentan.dao.IUserDao"/>-->
            <package name="com.kejizhentan.dao"/>
        </mappers>
    </configuration>
    
  • 创建映射配置文件
    IUserDao.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.kejizhentan.dao.IUserDao">
        <select id = "findById"   resultType="com.kejizhentan.bean.User">
            select * from user u where u.id = #{id}
        </select>
    </mapper>
    
  • 测试类:
    MybatisTest.java

    public class MybatisTest {
        private InputStream is;
        private SqlSession sqlSession;
        private IUserDao userDao;
        private SqlSessionFactory factory;
        /**
         * @Description 初始化加载资源的方法
         * @Author kejizhentan
         * @Date 2021/10/24 13:34
         **/
        @Before//用于在执行方法执行之前执行
        public void init() {
            try {
                //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(IUserDao.class);
            } catch (Exception e) {
                e.printStackTrace();
            }
        }
    
        /**
         * @Description 释放资源的方法
         * @Author kejizhentan
         * @Date 2021/10/24 13:34
         **/
        @After//用于在测试方法执行之后执行
        public void close() {
            //提交事务
            sqlSession.commit();
            //6.释放资源
            if (sqlSession != null) {
                sqlSession.close();
            }
            try {
                if (is != null) {
                    is.close();
                }
            } catch (Exception e) {
                e.printStackTrace();
            }
        }
    
        /**
         * @Description 测试mybatis的一级缓存
         * @Author kejizhentan
         * @Date 2021/11/6 12:00
         **/
        @Test
        public void findAll() {
            System.out.println("演示一级缓存");
            User user1 = userDao.findById(41);
            System.out.println(user1);
            User user2 = userDao.findById(41);
            System.out.println(user2);
            System.out.println(user1 == user2);
    
            //演示一级缓存失效的情况
            System.out.println("演示一级缓存失效的情况");
            User user3 = userDao.findById(42);
            System.out.println(user3);
            //使mybatis的一级缓存失效的两种方式:
            /*方式一:关闭sqlSession
            sqlSession.close();
            //再次获取sqlSession
            sqlSession = factory.openSession();
            userDao = sqlSession.getMapper(IUserDao.class);
            User user4 = dao.findById(42);
            System.out.println(user4);*/
            //方式二:使用clearCache方法清理缓存
            sqlSession.clearCache();
            User user4 = userDao.findById(42);
            System.out.println(user4);
            System.out.println(user3 == user4);
        }
    }
    
  • 结果如下:
    在这里插入图片描述

我们可以发现,虽然在上面的代码中我们查询了两次,但最后只执行了一次数据库操作,这就是 Mybatis提供给我们的一级缓存在起作用了。因为一级缓存的存在,导致第二次查询 id 为 41 的记录时,并没有发出 sql语句从数据库中查询数据,而是从一级缓存中查询。

② 触发清空一级缓存的情况

一级缓存是 SqlSession 范围的缓存,当调用 SqlSession 的修改,添加,删除,commit(),close()等方法时,就会清空一级缓存。
在这里插入图片描述

详细代码
  • 项目结构
    在这里插入图片描述

  • 创建maven工程并导入坐标

    <?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.kejizhentan</groupId>
        <artifactId>mybatis-project</artifactId>
        <version>1.0-SNAPSHOT</version>
        <packaging>jar</packaging>
        <dependencies>
            <!--Mybatis框架的依赖-->
            <dependency>
                <groupId>org.mybatis</groupId>
                <artifactId>mybatis</artifactId>
                <version>3.4.5</version>
            </dependency>
            <!--mysql数据库驱动的依赖-->
            <dependency>
                <groupId>mysql</groupId>
                <artifactId>mysql-connector-java</artifactId>
                <version>5.1.6</version>
            </dependency>
            <!--生成日志文件的依赖-->
            <dependency>
                <groupId>log4j</groupId>
                <artifactId>log4j</artifactId>
                <version>1.2.12</version>
            </dependency>
            <!--junit单元测试的依赖-->
            <dependency>
                <groupId>junit</groupId>
                <artifactId>junit</artifactId>
                <version>4.11</version>
                <scope>test</scope>
            </dependency>
        </dependencies>
    </project>
    
  • 创建实体类和dao的接口
    User.java

    public class User implements Serializable {
    private Integer id;
    private String username;
    private Date birthday;
    private String sex;
    private String address;
    
    public Integer getId() {
        return id;
    }
    
    public void setId(Integer id) {
        this.id = id;
    }
    
    public String getUsername() {
        return username;
    }
    
    public void setUsername(String username) {
        this.username = username;
    }
    
    public Date getBirthday() {
        return birthday;
    }
    
    public void setBirthday(Date birthday) {
        this.birthday = birthday;
    }
    
    public String getSex() {
        return sex;
    }
    
    public void setSex(String sex) {
        this.sex = sex;
    }
    
    public String getAddress() {
        return address;
    }
    
    public void setAddress(String address) {
        this.address = address;
    }
    
    }
    

    IUserDao.java

    public interface IUserDao {
    /**
     * @Description 查询所有用户的方法
     * @Author kejizhentan
     * @Date 2021/10/24 12:51
     **/
    User findById(Integer id);
    }
    /**
     * @Description 新增用户信息
     * @Author kejizhentan
     * @Date 2021/11/7 15:41
     **/
    void updateUser(User user);
    
  • 创建Mybatis的主配置文件
    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">
    <!--Mybatis的主配置文件-->
    <configuration>
        <!--配置环境-->
        <environments default="mysql">
            <!--配置mysql环境-->
            <environment id="mysql">
                <!--配置事务的类型-->
                <transactionManager type="JDBC"></transactionManager>
                <!--配置数据源(连接池)-->
                <dataSource type="POOLED">
                    <!--配置数据的四个基本信息-->
                    <property name="driver" value="com.mysql.jdbc.Driver"/>
                    <property name="url" value="jdbc:mysql://localhost:3306/db4"/>
                    <property name="username" value="root"/>
                    <property name="password" value="root"/>
                </dataSource>
            </environment>
        </environments>
        <!--
         使用配置文件来实现mybatis的配置:
            指定映射配置文件的位置,映射配置文件指的是每个dao独立的配置文件
         使用注解来实现mybatis的配置:
            如果使用注解来配置的话,此处应该使用class属性指定被注解的dao全限制类名
        -->
        <mappers>
            <!--<mapper resource="com/kejizhentan/dao/IAccountDao.xml"/>-->
            <!--<mapper class="com.kejizhentan.dao.IUserDao"/>-->
            <package name="com.kejizhentan.dao"/>
        </mappers>
    </configuration>
    
  • 创建映射配置文件
    IUserDao.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.kejizhentan.dao.IUserDao">
        <select id = "findById"   resultType="com.kejizhentan.bean.User">
            select * from user u where u.id = #{id}
        </select>
        <!--更新用户信息-->
        <update id="updateUser" parameterType="com.kejizhentan.bean.User">
            update user set username = #{username},address = #{address} where id = #{id}
        </update>
    </mapper>
    
  • 测试类:
    MybatisTest.java

    public class MybatisTest {
        private InputStream is;
        private SqlSession sqlSession;
        private IUserDao userDao;
        private SqlSessionFactory factory;
        /**
         * @Description 初始化加载资源的方法
         * @Author kejizhentan
         * @Date 2021/10/24 13:34
         **/
        @Before//用于在执行方法执行之前执行
        public void init() {
            try {
                //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(IUserDao.class);
            } catch (Exception e) {
                e.printStackTrace();
            }
        }
    
        /**
         * @Description 释放资源的方法
         * @Author kejizhentan
         * @Date 2021/10/24 13:34
         **/
        @After//用于在测试方法执行之后执行
        public void close() {
            //提交事务
            sqlSession.commit();
            //6.释放资源
            if (sqlSession != null) {
                sqlSession.close();
            }
            try {
                if (is != null) {
                    is.close();
                }
            } catch (Exception e) {
                e.printStackTrace();
            }
        }
    
        /**
         * @Description 测试mybatis的一级缓存
         * @Author kejizhentan
         * @Date 2021/11/6 12:00
         **/
        @Test
        public void findAll() {
            System.out.println("演示一级缓存");
            User user1 = userDao.findById(41);
            System.out.println(user1);
            user1.setUsername("触发清空一级缓存");
            user1.setAddress("北京市海淀区");
            //更新用户信息
            userDao.updateUser(user1);
            //再次查询41的用户信息
            User user2 = userDao.findById(41);
            System.out.println(user2);
            System.out.println(user1 == user2);
        }
    }
    
  • 结果如下:
    在这里插入图片描述

⑵ 二级缓存:

它指的是Mybatis中SqlSessionFactory对象的缓存。由同一个SqlSessionFactory对象创建的SqlSession共享其缓存。
在这里插入图片描述

二级缓存的使用步骤
第一步:让Mybatis框架支持二级缓存(在SqlMapConfig.xml中配置)
第二步:让当前的映射文件支持二级缓存(在IUserDao.xml中配置)
第三步:让当前的操作支持二级缓存(在select标签中配置)

详细代码
  • 项目结构
    在这里插入图片描述

  • 创建maven工程并导入坐标

    <?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.kejizhentan</groupId>
        <artifactId>mybatis-project</artifactId>
        <version>1.0-SNAPSHOT</version>
        <packaging>jar</packaging>
        <dependencies>
            <!--Mybatis框架的依赖-->
            <dependency>
                <groupId>org.mybatis</groupId>
                <artifactId>mybatis</artifactId>
                <version>3.4.5</version>
            </dependency>
            <!--mysql数据库驱动的依赖-->
            <dependency>
                <groupId>mysql</groupId>
                <artifactId>mysql-connector-java</artifactId>
                <version>5.1.6</version>
            </dependency>
            <!--生成日志文件的依赖-->
            <dependency>
                <groupId>log4j</groupId>
                <artifactId>log4j</artifactId>
                <version>1.2.12</version>
            </dependency>
            <!--junit单元测试的依赖-->
            <dependency>
                <groupId>junit</groupId>
                <artifactId>junit</artifactId>
                <version>4.11</version>
                <scope>test</scope>
            </dependency>
        </dependencies>
    </project>
    
  • 创建实体类和dao的接口
    User.java

    public class User implements Serializable {
    private Integer id;
    private String username;
    private Date birthday;
    private String sex;
    private String address;
    
    public Integer getId() {
        return id;
    }
    
    public void setId(Integer id) {
        this.id = id;
    }
    
    public String getUsername() {
        return username;
    }
    
    public void setUsername(String username) {
        this.username = username;
    }
    
    public Date getBirthday() {
        return birthday;
    }
    
    public void setBirthday(Date birthday) {
        this.birthday = birthday;
    }
    
    public String getSex() {
        return sex;
    }
    
    public void setSex(String sex) {
        this.sex = sex;
    }
    
    public String getAddress() {
        return address;
    }
    
    public void setAddress(String address) {
        this.address = address;
    }
    
    }
    

    IUserDao.java

    public interface IUserDao {
    /**
     * @Description 查询所有用户的方法
     * @Author kejizhentan
     * @Date 2021/10/24 12:51
     **/
    User findById(Integer id);
    }
    
    
  • 创建Mybatis的主配置文件
    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">
    <!--Mybatis的主配置文件-->
    <configuration>
        <!--让Mybatis框架支持二级缓存(在SqlMapConfig.xml中配置)-->
        <settings>
            <setting name="cacheEnabled" value="true"/>
        </settings>
        <!--配置环境-->
        <environments default="mysql">
            <!--配置mysql环境-->
            <environment id="mysql">
                <!--配置事务的类型-->
                <transactionManager type="JDBC"></transactionManager>
                <!--配置数据源(连接池)-->
                <dataSource type="POOLED">
                    <!--配置数据的四个基本信息-->
                    <property name="driver" value="com.mysql.jdbc.Driver"/>
                    <property name="url" value="jdbc:mysql://localhost:3306/db4"/>
                    <property name="username" value="root"/>
                    <property name="password" value="root"/>
                </dataSource>
            </environment>
        </environments>
        <!--
         使用配置文件来实现mybatis的配置:
            指定映射配置文件的位置,映射配置文件指的是每个dao独立的配置文件
         使用注解来实现mybatis的配置:
            如果使用注解来配置的话,此处应该使用class属性指定被注解的dao全限制类名
        -->
        <mappers>
            <!--<mapper resource="com/kejizhentan/dao/IAccountDao.xml"/>-->
            <!--<mapper class="com.kejizhentan.dao.IUserDao"/>-->
            <package name="com.kejizhentan.dao"/>
        </mappers>
    </configuration>
    
  • 创建映射配置文件
    IUserDao.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.kejizhentan.dao.IUserDao">
        <!--让当前的映射文件支持二级缓存(在IUserDao.xml中配置)-->
         <cache/>
         <!--让当前的操作支持二级缓存(在select标签中配置)-->
        <select id = "findById" parameterType="int"  resultType="com.kejizhentan.bean.User" useCache="true">
            select * from user u where u.id = #{id}
        </select>
    </mapper>
    
  • 测试类:
    MybatisTest.java

    public class MybatisTest {
        private InputStream is;
        private SqlSessionFactory factory;
        /**
         * @Description 初始化加载资源的方法
         * @Author kejizhentan
         * @Date 2021/10/24 13:34
         **/
        @Before//用于在执行方法执行之前执行
        public void init() {
            try {
                //1.读取配置文件
                is = Resources.getResourceAsStream("SqlMapConfig.xml");
                //2.创建SqlSessionFactory工厂
                SqlSessionFactoryBuilder builder = new SqlSessionFactoryBuilder();
                factory = builder.build(is);
            } catch (Exception e) {
                e.printStackTrace();
            }
        }
    
        /**
         * @Description 释放资源的方法
         * @Author kejizhentan
         * @Date 2021/10/24 13:34
         **/
        @After//用于在测试方法执行之后执行
        public void close() {
            try {
                if (is != null) {
                    is.close();
                }
            } catch (Exception e) {
                e.printStackTrace();
            }
        }
    
        /**
         * @Description 测试mybatis的一级缓存
         * @Author kejizhentan
         * @Date 2021/11/6 12:00
         **/
        @Test
        public void findAll() {
            System.out.println("演示二级缓存");
            SqlSession sqlSession1= factory.openSession();
            IUserDao userDao1 = sqlSession1.getMapper(IUserDao.class);
            User user1 = userDao1.findById(41);
            System.out.println(user1);
            sqlSession1.close();//一级缓存消失
    
            SqlSession sqlSession2= factory.openSession();
            IUserDao userDao2 = sqlSession2.getMapper(IUserDao.class);
            User user2 = userDao2.findById(41);
            sqlSession2.close();//一级缓存消失
            System.out.println(user2);
            System.out.println(user1 == user2);
        }
    }
    
  • 结果如下:
    在这里插入图片描述

注意:
二级缓存中存储的是数据不是对象,当使用二级缓存中的数据时会创建一个新对象,将缓存中的数据填充到这个新对象中。所以上面两个对象的值不相等。在这里插入图片描述

十七、综合练习(使用注解的方式完成基本的CRUD操作、多表查询和缓存的使用)

1. 使用注解的方式完成基本的CRUD操作

详细代码:

  • 项目结构
    在这里插入图片描述

  • 创建maven工程并导入坐标

    <?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.kejizhentan</groupId>
        <artifactId>mybatis-annotation</artifactId>
        <version>1.0-SNAPSHOT</version>
        <packaging>jar</packaging>
    
        <dependencies>
            <!--导入mybatis依赖包-->
            <dependency>
                <groupId>org.mybatis</groupId>
                <artifactId>mybatis</artifactId>
                <version>3.4.5</version>
            </dependency>
            <!--导入mysql的连接依赖包-->
            <dependency>
                <groupId>mysql</groupId>
                <artifactId>mysql-connector-java</artifactId>
                <version>5.1.6</version>
            </dependency>
            <!--导入日志文件logo4j的依赖-->
            <dependency>
                <groupId>log4j</groupId>
                <artifactId>log4j</artifactId>
                <version>1.2.12</version>
            </dependency>
            <!--导入单元测试的依赖-->
            <dependency>
                <groupId>junit</groupId>
                <artifactId>junit</artifactId>
                <version>4.10</version>
            </dependency>
        </dependencies>
    </project>
    
  • 创建实体类和dao的接口
    User.java

    	public class User implements Serializable {
    
        private Integer id;
        private String username;
        private String address;
        private String sex;
        private Date birthday;
        public Integer getId() {
            return id;
        }
    
        public void setId(Integer id) {
            this.id = id;
        }
    
        public String getUsername() {
            return username;
        }
    
        public void setUsername(String username) {
            this.username = username;
        }
    
        public String getAddress() {
            return address;
        }
    
        public void setAddress(String address) {
            this.address = address;
        }
    
        public String getSex() {
            return sex;
        }
    
        public void setSex(String sex) {
            this.sex = sex;
        }
    
        public Date getBirthday() {
            return birthday;
        }
    
        public void setBirthday(Date birthday) {
            this.birthday = birthday;
        }
    
        @Override
        public String toString() {
            return "User{" +
                    "id=" + id +
                    ", username='" + username + '\'' +
                    ", address='" + address + '\'' +
                    ", sex='" + sex + '\'' +
                    ", birthday=" + birthday +
                    '}';
        }
    }
    
    

    IUserDao.java

    public interface IUserDao {
    //查询所有的用户信息
    @Select("select * from user")
    List<User> findAll();
    
    /**
     * 保存用户
     * @param user
     */
    @Insert("insert into user(username,address,sex,birthday)values(#{username},#{address},#{sex},#{birthday})")
    void saveUser(User user);
    
    /**
     * 更新用户
     * @param user
     */
    @Update("update user set username=#{username},sex=#{sex},birthday=#{birthday},address=#{address} where id=#{id}")
    void updateUser(User user);
    
    /**
     * 删除用户
     * @param userId
     */
    @Delete("delete from user where id=#{id} ")
    void deleteUser(Integer userId);
    
    /**
     * 根据id查询用户
     * @param userId
     * @return
     */
    @Select("select * from user  where id=#{id} ")
    User findById(Integer userId);
    
    /**
     * 根据用户名称模糊查询
     * @param username
     * @return
     */
    //@Select("select * from user where username like #{username} ")
        @Select("select * from user where username like CONCAT('%',#{username},'%') ")
        List<User> findUserByName(String username);
    
        /**
         * 查询总用户数量
         * @return
         */
        @Select("select count(*) from user ")
        int findTotalUser();
    }
    
  • 创建Mybatis的主配置文件
    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>
        <!-- 配置引入properties-->
        <properties resource="jdbcConfig.properties"></properties>
        <!--配置别名-->
        <typeAliases>
            <package name="com.kejizhentan.bean"></package>
        </typeAliases>
        <!--配置环境-->
        <environments default="mysql">
            <!-- 配置mysql的环境-->
            <environment id="mysql">
                <!-- 配置事务 -->
                <transactionManager type="JDBC"></transactionManager>
                <!--配置连接池-->
                <dataSource type="POOLED">
                    <property name="driver" value="${jdbc.driver}"></property>
                    <property name="url" value="${jdbc.url}"></property>
                    <property name="username" value="${jdbc.username}"></property>
                    <property name="password" value="${jdbc.password}"></property>
                </dataSource>
            </environment>
        </environments>
        <!-- 配置映射文件的位置 -->
        <mappers>
            <package name="com.kejizhentan.dao"></package>
        </mappers>
    </configuration>
    
  • jdbcConfig.properties

    jdbc.driver=com.mysql.jdbc.Driver
    jdbc.url=jdbc:mysql://localhost:3306/kjztdatabase
    jdbc.username=root
    jdbc.password=123456
    
  • 测试类:
    MybatisTest.java

    public class MybatisTest {
    private InputStream in;
    private SqlSession sqlSession;
    private IUserDao userDao;
    
    @Before//用于在测试方法执行之前执行
    public void init()throws Exception{
        //1.读取配置文件,生成字节输入流
        in = Resources.getResourceAsStream("SqlMapConfig.xml");
        //2.获取SqlSessionFactory
        SqlSessionFactory factory = new SqlSessionFactoryBuilder().build(in);
        //3.获取SqlSession对象
        sqlSession = factory.openSession(true);
        //4.获取dao的代理对象
        userDao = sqlSession.getMapper(IUserDao.class);
    }
    
    @After//用于在测试方法执行之后执行
    public void destroy()throws Exception{
        //提交事务
        // sqlSession.commit();
        //6.释放资源
        sqlSession.close();
        in.close();
        }
    
        /**
         * 测试查询所有
         */
        @Test
        public void testFindAll(){
            List<User> users = userDao.findAll();
            for (User user : users) {
                System.out.println(user);
            }
        }
    
        @Test
        public void testSave(){
            User user = new User();
            user.setUsername("mybatis annotation");
            user.setAddress("北京市昌平区");
    
            userDao.saveUser(user);
        }
    
        @Test
        public void testUpdate(){
            User user = new User();
            user.setId(49);
            user.setUsername("mybatis annotation update");
            user.setAddress("北京市海淀区");
            user.setSex("男");
            user.setBirthday(new Date());
    
            userDao.updateUser(user);
        }
    
    
        @Test
        public void testDelete(){
            userDao.deleteUser(49);
        }
    
        @Test
        public void testFindOne(){
            User user = userDao.findById(48);
            System.out.println(user);
        }
    
    
        @Test
        public  void testFindByName(){
    //        List<User> users = userDao.findUserByName("%mybatis%");
            List<User> users = userDao.findUserByName("小二王");
            for(User user : users){
                System.out.println(user);
            }
        }
    
        @Test
        public  void testFindTotal(){
            int total = userDao.findTotalUser();
            System.out.println(total);
        }
    }
    
  • 结果如下:
    在这里插入图片描述

注意:
使用注解开发时,当实体类属性和数据库字段不匹配时,可以使用@Results和@Result注解解决实体字段和数据库的字段不对应的问题:
在这里插入图片描述

2. 使用注解的方式完成一对一多表操作

在这里插入图片描述

详细代码:

  • 项目结构
    在这里插入图片描述

  • 创建maven工程并导入坐标

    <?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.kejizhentan</groupId>
        <artifactId>mybatis-annotation</artifactId>
        <version>1.0-SNAPSHOT</version>
        <packaging>jar</packaging>
    
        <dependencies>
            <!--导入mybatis依赖包-->
            <dependency>
                <groupId>org.mybatis</groupId>
                <artifactId>mybatis</artifactId>
                <version>3.4.5</version>
            </dependency>
            <!--导入mysql的连接依赖包-->
            <dependency>
                <groupId>mysql</groupId>
                <artifactId>mysql-connector-java</artifactId>
                <version>5.1.6</version>
            </dependency>
            <!--导入日志文件logo4j的依赖-->
            <dependency>
                <groupId>log4j</groupId>
                <artifactId>log4j</artifactId>
                <version>1.2.12</version>
            </dependency>
            <!--导入单元测试的依赖-->
            <dependency>
                <groupId>junit</groupId>
                <artifactId>junit</artifactId>
                <version>4.10</version>
            </dependency>
        </dependencies>
    </project>
    
  • 创建实体类和dao的接口
    User.java

    	public class User implements Serializable {
    
        private Integer id;
        private String username;
        private String address;
        private String sex;
        private Date birthday;
        public Integer getId() {
            return id;
        }
    
        public void setId(Integer id) {
            this.id = id;
        }
    
        public String getUsername() {
            return username;
        }
    
        public void setUsername(String username) {
            this.username = username;
        }
    
        public String getAddress() {
            return address;
        }
    
        public void setAddress(String address) {
            this.address = address;
        }
    
        public String getSex() {
            return sex;
        }
    
        public void setSex(String sex) {
            this.sex = sex;
        }
    
        public Date getBirthday() {
            return birthday;
        }
    
        public void setBirthday(Date birthday) {
            this.birthday = birthday;
        }
    
        @Override
        public String toString() {
            return "User{" +
                    "id=" + id +
                    ", username='" + username + '\'' +
                    ", address='" + address + '\'' +
                    ", sex='" + sex + '\'' +
                    ", birthday=" + birthday +
                    '}';
        }
    }
    
    

    IUserDao.java

    public interface IUserDao {
    /**
     * 根据id查询用户
     * @param userId
     * @return
     */
    @Select("select * from user  where id=#{id}")
    User findById(Integer userId);
    }
    

    Account.java

    public class Account implements Serializable {
    
        private Integer id;
        private Integer uid;
        private Double money;
    
        //从表实体应该包含一个主表实体的对象引用
        private User user;
    
        public User getUser() {
            return user;
        }
    
        public void setUser(User user) {
            this.user = user;
        }
    
        public Integer getId() {
            return id;
        }
    
        public void setId(Integer id) {
            this.id = id;
        }
    
        public Integer getUid() {
            return uid;
        }
    
        public void setUid(Integer uid) {
            this.uid = uid;
        }
    
        public Double getMoney() {
            return money;
        }
    
        public void setMoney(Double money) {
            this.money = money;
        }
    
        @Override
        public String toString() {
            return "Account{" +
                    "id=" + id +
                    ", uid=" + uid +
                    ", money=" + money +
                    ", user=" + user +
                    '}';
        }
    }
    

    IAccountdao.java

    public interface IAccountDao {
        /**
         * 查询所有账户,同时还要获取到当前账户的所属用户信息
         * @return
         */
        /**
         * 查询所有账户,并且获取每个账户所属的用户信息
         * @return
         */
        @Select("select * from account")
        @Results({
                @Result(id=true,column = "id",property = "id"),
                @Result(column = "uid",property = "uid"),
                @Result(column = "money",property = "money"),
                @Result(property = "user",column = "uid",one=@One(select="com.kejizhentan.dao.IUserDao.findById",fetchType= FetchType.EAGER))
        })
        List<Account> findAll();
    }
    
  • 创建Mybatis的主配置文件
    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>
        <!-- 配置引入properties-->
        <properties resource="jdbcConfig.properties"></properties>
        <!--配置别名-->
        <typeAliases>
            <package name="com.kejizhentan.bean"></package>
        </typeAliases>
        <!--配置环境-->
        <environments default="mysql">
            <!-- 配置mysql的环境-->
            <environment id="mysql">
                <!-- 配置事务 -->
                <transactionManager type="JDBC"></transactionManager>
                <!--配置连接池-->
                <dataSource type="POOLED">
                    <property name="driver" value="${jdbc.driver}"></property>
                    <property name="url" value="${jdbc.url}"></property>
                    <property name="username" value="${jdbc.username}"></property>
                    <property name="password" value="${jdbc.password}"></property>
                </dataSource>
            </environment>
        </environments>
        <!-- 配置映射文件的位置 -->
        <mappers>
            <package name="com.kejizhentan.dao"></package>
        </mappers>
    </configuration>
    
  • jdbcConfig.properties

    jdbc.driver=com.mysql.jdbc.Driver
    jdbc.url=jdbc:mysql://localhost:3306/kjztdatabase
    jdbc.username=root
    jdbc.password=123456
    
  • 测试类:
    MybatisTest.java

    public class MybatisTest {
    private InputStream in;
    private SqlSession sqlSession;
    private IAccountDao accountDao;
    
    @Before//用于在测试方法执行之前执行
    public void init()throws Exception{
        //1.读取配置文件,生成字节输入流
        in = Resources.getResourceAsStream("SqlMapConfig.xml");
        //2.获取SqlSessionFactory
        SqlSessionFactory factory = new SqlSessionFactoryBuilder().build(in);
        //3.获取SqlSession对象
        sqlSession = factory.openSession(true);
        //4.获取dao的代理对象
        accountDao = sqlSession.getMapper(IAccountDao.class);
    }
    
    @After//用于在测试方法执行之后执行
    public void destroy()throws Exception{
        //提交事务
        // sqlSession.commit();
        //6.释放资源
        sqlSession.close();
        in.close();
    }
    @Test
    public void testFindAll(){
        List<Account> accounts = accountDao.findAll();
        for (Account account : accounts) {
            System.out.println(account);
        }
    }
    }
    
  • 结果如下:
    在这里插入图片描述

3. 使用注解的方式完成一对多的多表操作

详细代码:

  • 项目结构
    在这里插入图片描述

  • 创建maven工程并导入坐标

    <?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.kejizhentan</groupId>
        <artifactId>mybatis-annotation</artifactId>
        <version>1.0-SNAPSHOT</version>
        <packaging>jar</packaging>
    
        <dependencies>
            <!--导入mybatis依赖包-->
            <dependency>
                <groupId>org.mybatis</groupId>
                <artifactId>mybatis</artifactId>
                <version>3.4.5</version>
            </dependency>
            <!--导入mysql的连接依赖包-->
            <dependency>
                <groupId>mysql</groupId>
                <artifactId>mysql-connector-java</artifactId>
                <version>5.1.6</version>
            </dependency>
            <!--导入日志文件logo4j的依赖-->
            <dependency>
                <groupId>log4j</groupId>
                <artifactId>log4j</artifactId>
                <version>1.2.12</version>
            </dependency>
            <!--导入单元测试的依赖-->
            <dependency>
                <groupId>junit</groupId>
                <artifactId>junit</artifactId>
                <version>4.10</version>
            </dependency>
        </dependencies>
    </project>
    
  • 创建实体类和dao的接口
    User.java

    public class User implements Serializable {
        private Integer id;
        private String username;
        private String address;
        private String sex;
        private Date birthday;
        private List<Account> accounts;
    
        public List<Account> getAccounts() {
            return accounts;
        }
    
        public void setAccounts(List<Account> accounts) {
            this.accounts = accounts;
        }
    
        public Integer getId() {
            return id;
        }
    
        public void setId(Integer id) {
            this.id = id;
        }
    
        public String getUsername() {
            return username;
        }
    
        public void setUsername(String username) {
            this.username = username;
        }
    
        public String getAddress() {
            return address;
        }
    
        public void setAddress(String address) {
            this.address = address;
        }
    
        public String getSex() {
            return sex;
        }
    
        public void setSex(String sex) {
            this.sex = sex;
        }
    
        public Date getBirthday() {
            return birthday;
        }
    
        public void setBirthday(Date birthday) {
            this.birthday = birthday;
        }
    
        @Override
        public String toString() {
            return "User{" +
                    "id=" + id +
                    ", username='" + username + '\'' +
                    ", address='" + address + '\'' +
                    ", sex='" + sex + '\'' +
                    ", birthday=" + birthday +
                    ", accounts=" + accounts +
                    '}';
        }
    }
    

    IUserDao.java

    public interface IUserDao {
    /**
     * 查询所有用户
     * @return
     */
    @Select("select * from user")
    @Results({
            @Result(id=true,column = "id",property = "id"),
            @Result(column = "username",property = "username"),
            @Result(column = "address",property = "address"),
            @Result(column = "sex",property = "sex"),
            @Result(column = "birthday",property = "birthday"), @Result(property = "accounts",column = "id", many = @Many(select = "com.kejizhentan.dao.IAccountDao.findByUid", fetchType = FetchType.LAZY)) }) List<User> findAll();
    }
    

    Account.java

    public class Account implements Serializable {
    
    private Integer id;
    private Integer uid;
    private Double money;
    
    public Integer getId() {
        return id;
    }
    
    public void setId(Integer id) {
        this.id = id;
    }
    
    public Integer getUid() {
        return uid;
    }
    
    public void setUid(Integer uid) {
        this.uid = uid;
    }
    
    public Double getMoney() {
        return money;
    }
    
    public void setMoney(Double money) {
        this.money = money;
    }
    
    @Override
    public String toString() {
        return "Account{" +
                "id=" + id +
                ", uid=" + uid +
                ", money=" + money +
                '}';
    }
    }
    
    

    IAccountdao.java

    public interface IAccountDao {
    /**
     * 根据uid查询账户信息
     */
    @Select("select * from account where uid = #{uid}")
    List<Account> findByUid(Integer uid);
    }
    
  • 创建Mybatis的主配置文件
    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>
        <!-- 配置引入properties-->
        <properties resource="jdbcConfig.properties"></properties>
        <!--配置别名-->
        <typeAliases>
            <package name="com.kejizhentan.bean"></package>
        </typeAliases>
        <!--配置环境-->
        <environments default="mysql">
            <!-- 配置mysql的环境-->
            <environment id="mysql">
                <!-- 配置事务 -->
                <transactionManager type="JDBC"></transactionManager>
                <!--配置连接池-->
                <dataSource type="POOLED">
                    <property name="driver" value="${jdbc.driver}"></property>
                    <property name="url" value="${jdbc.url}"></property>
                    <property name="username" value="${jdbc.username}"></property>
                    <property name="password" value="${jdbc.password}"></property>
                </dataSource>
            </environment>
        </environments>
        <!-- 配置映射文件的位置 -->
        <mappers>
            <package name="com.kejizhentan.dao"></package>
        </mappers>
    </configuration>
    
  • jdbcConfig.properties

    jdbc.driver=com.mysql.jdbc.Driver
    jdbc.url=jdbc:mysql://localhost:3306/kjztdatabase
    jdbc.username=root
    jdbc.password=123456
    
  • 测试类:
    MybatisTest.java

    public class MybatisTest {
    private InputStream in;
    private SqlSession sqlSession;
    private IUserDao userDao;
    
    @Before//用于在测试方法执行之前执行
    public void init()throws Exception{
        //1.读取配置文件,生成字节输入流
        in = Resources.getResourceAsStream("SqlMapConfig.xml");
        //2.获取SqlSessionFactory
        SqlSessionFactory factory = new SqlSessionFactoryBuilder().build(in);
        //3.获取SqlSession对象
        sqlSession = factory.openSession(true);
        //4.获取dao的代理对象
        userDao = sqlSession.getMapper(IUserDao.class);
    }
    
    @After//用于在测试方法执行之后执行
    public void destroy()throws Exception{
        //提交事务
        // sqlSession.commit();
        //6.释放资源
        sqlSession.close();
        in.close();
    }
    @Test
    public void testFindAll(){
        List<User> users = userDao.findAll();
        for (User user : users) {
            System.out.println(user);
        }
    }
    }
    
  • 结果如下:
    在这里插入图片描述

4. 使用mybatis注解开发时如何开启二级缓存

在这里插入图片描述
详细代码:

  • 项目结构
    在这里插入图片描述

  • 创建maven工程并导入坐标

    <?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.kejizhentan</groupId>
        <artifactId>mybatis-annotation</artifactId>
        <version>1.0-SNAPSHOT</version>
        <packaging>jar</packaging>
    
        <dependencies>
            <!--导入mybatis依赖包-->
            <dependency>
                <groupId>org.mybatis</groupId>
                <artifactId>mybatis</artifactId>
                <version>3.4.5</version>
            </dependency>
            <!--导入mysql的连接依赖包-->
            <dependency>
                <groupId>mysql</groupId>
                <artifactId>mysql-connector-java</artifactId>
                <version>5.1.6</version>
            </dependency>
            <!--导入日志文件logo4j的依赖-->
            <dependency>
                <groupId>log4j</groupId>
                <artifactId>log4j</artifactId>
                <version>1.2.12</version>
            </dependency>
            <!--导入单元测试的依赖-->
            <dependency>
                <groupId>junit</groupId>
                <artifactId>junit</artifactId>
                <version>4.10</version>
            </dependency>
        </dependencies>
    </project>
    
  • 创建实体类和dao的接口
    User.java

    	public class User implements Serializable {
    
        private Integer id;
        private String username;
        private String address;
        private String sex;
        private Date birthday;
        public Integer getId() {
            return id;
        }
    
        public void setId(Integer id) {
            this.id = id;
        }
    
        public String getUsername() {
            return username;
        }
    
        public void setUsername(String username) {
            this.username = username;
        }
    
        public String getAddress() {
            return address;
        }
    
        public void setAddress(String address) {
            this.address = address;
        }
    
        public String getSex() {
            return sex;
        }
    
        public void setSex(String sex) {
            this.sex = sex;
        }
    
        public Date getBirthday() {
            return birthday;
        }
    
        public void setBirthday(Date birthday) {
            this.birthday = birthday;
        }
    
        @Override
        public String toString() {
            return "User{" +
                    "id=" + id +
                    ", username='" + username + '\'' +
                    ", address='" + address + '\'' +
                    ", sex='" + sex + '\'' +
                    ", birthday=" + birthday +
                    '}';
        }
    }
    
    

    IUserDao.java

    //配置二级缓存的注解
    @CacheNamespace(blocking=true)
    public interface IUserDao {
        /**
         * 查询所有用户
         * @return
         */
        @Select("select * from user where id = #{id}")
        User findById(Integer id);
    }
    
  • 创建Mybatis的主配置文件
    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>
        <!-- 配置引入properties-->
        <properties resource="jdbcConfig.properties"></properties>
        <!--配置开启二级缓存-->
        <settings>
            <setting name="cacheEnabled" value="true"/>
        </settings>
        <!--配置别名-->
        <typeAliases>
            <package name="com.kejizhentan.bean"></package>
        </typeAliases>
        <!--配置环境-->
        <environments default="mysql">
            <!-- 配置mysql的环境-->
            <environment id="mysql">
                <!-- 配置事务 -->
                <transactionManager type="JDBC"></transactionManager>
                <!--配置连接池-->
                <dataSource type="POOLED">
                    <property name="driver" value="${jdbc.driver}"></property>
                    <property name="url" value="${jdbc.url}"></property>
                    <property name="username" value="${jdbc.username}"></property>
                    <property name="password" value="${jdbc.password}"></property>
                </dataSource>
            </environment>
        </environments>
        <!-- 配置映射文件的位置 -->
        <mappers>
            <package name="com.kejizhentan.dao"></package>
        </mappers>
    </configuration>
    
  • jdbcConfig.properties

    jdbc.driver=com.mysql.jdbc.Driver
    jdbc.url=jdbc:mysql://localhost:3306/kjztdatabase
    jdbc.username=root
    jdbc.password=123456
    
  • 测试类:
    MybatisTest.java

    public class MybatisTest {
        private InputStream in;
        private SqlSessionFactory factory;
        @Before//用于在测试方法执行之前执行
        public void init()throws Exception{
            //1.读取配置文件,生成字节输入流
            in = Resources.getResourceAsStream("SqlMapConfig.xml");
            //2.获取SqlSessionFactory
            factory  = new SqlSessionFactoryBuilder().build(in);
        }
    
        @After//用于在测试方法执行之后执行
        public void destroy()throws Exception{
            //提交事务
            // sqlSession.commit();
            //6.释放资源
            in.close();
        }
        @Test
        public void testFindById(){
            SqlSession sqlSession1 = factory.openSession();
            IUserDao dao1 = sqlSession1.getMapper(IUserDao.class);
            User user1 = dao1.findById(46);
            System.out.println(user1);
            sqlSession1.close();//一级缓存消失
    
            SqlSession sqlSession2 = factory.openSession();
            IUserDao dao2 = sqlSession2.getMapper(IUserDao.class);
            User user2 = dao2.findById(46);
            System.out.println(user2);
            sqlSession2.close();
    
            System.out.println(user1 == user2);
        }
    }
    
  • 结果如下:
    在这里插入图片描述

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值