• MyBatis基础教程


    文章目录


    一、MyBatis基本使用

    1.1简介

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

      什么是持久化?持久化是将程序数据在持久状态和瞬时状态间转换的机制,即把数据(如内存中的对象)保存到可永久保存的存储设备中(如磁盘)。持久化的主要应用是将内存中的对象存储在数据库中,或者存储在磁盘文件中、XML数据文件中等等,JDBC就是一种持久化机制、文件IO也是一种持久化机制。

      什么是持久层?:持久层(dao层,Data Access Object数据访问对象)用于完成持久化工作,即,将内存中的数据保存到磁盘上加以固化,而持久化的实现过程则大多通过各种关系数据库来完成。

    MyBatis具有以下特性
    在这里插入图片描述
    与其他持久化层技术对比
    在这里插入图片描述

    MyBatis官方地址MyBatis3

    1.2搭建MyBatis环境

    1.2.1安装MyBatis

      引入依赖:

    <!--MyBatis 依赖-->
    <dependency>
        <groupId>org.mybatis</groupId>
        <artifactId>mybatis</artifactId>
        <version>3.5.7</version>
    </dependency>
    <!--junit5测试-->
    <dependency>
        <groupId>org.junit.jupiter</groupId>
        <artifactId>junit-jupiter-api</artifactId>
        <version>5.10.2</version>
        <scope>test</scope>
    </dependency>
    <!--MySQL驱动-->
    <dependency>
        <groupId>mysql</groupId>
        <artifactId>mysql-connector-java</artifactId>
        <version>8.0.18</version>
    </dependency>
    

      其中,mysql-connector-java是MySQL提供的JDBC驱动包,用JDBC连接MySQL数据库时必须使用该jar包。注意,本文中安装的MySQL版本为8.0.18。

    1.2.2创建MyBatis核心配置文件

      习惯上将MyBatis核心配置文件命名为mybatis-config.xml,在整合Spring之后可省略。核心配置文件主要用于配置连接数据库的环境以及MyBatis的全局配置信息,存放在src/main/resources目录下。可在IDEA中保存配置文件的官方模板:

    
    DOCTYPE configuration
      PUBLIC "-//mybatis.org//DTD Config 3.0//EN"
      "https://mybatis.org/dtd/mybatis-3-config.dtd">
    <configuration>
    	
      <environments default="development">
        <environment id="development">
          <transactionManager type="JDBC"/>
          <dataSource type="POOLED">
            <property name="driver" value="${driver}"/>
            <property name="url" value="${url}"/>
            <property name="username" value="${username}"/>
            <property name="password" value="${password}"/>
          dataSource>
        environment>
      environments>
      
      <mappers>
        <mapper resource="org/mybatis/example/BlogMapper.xml"/>
      mappers>
    configuration>
    

    在这里插入图片描述
    在之后创建配置文件时只需输入信息即可:
    在这里插入图片描述
    所输入信息为:

    File name:mybatis-config.xml
    driver:com.mysql.cj.jdbc.Driver
    url:jdbc:mysql://localhost:3306/testdatabase?serverTimezone=Asia/Shanghai&useUnicode=true&characterEncoding=utf8&useSSL=true
    username:root
    password:123456
    

    其中,数据库testdatabase会在下文中创建。

    1.2.3创建mapper接口

      MyBatis中的mapper接口相当于以前的dao接口,但区别在于mapper仅仅是接口,无需创建实现类。当调用接口中的方法时,就会自动找到对应的SQL语句并执行。
    1.创建数据库及user表

    create database testdatabase;
    use testdatabase;
    create table table_user
    (
        id       int auto_increment,
        name     varchar(20) null,
        password varchar(20) null,
        age      int         null,
        sex      char        null,
        email    varchar(20) null,
        constraint table_user_pk
            primary key (id)
    );
    

    2.创建实体类User:本项目中将所有实体类放在同一目录Pojo下。

    package org.example.Pojo;
    
    public class User {
        private Integer id;
        private String username;
        private String password;
        private Integer age;
        private String sex;
        private String email;
    
        public User() {
        }
    
        public User(Integer id, String username, String password, Integer age, String sex, String email) {
            this.id = id;
            this.username = username;
            this.password = password;
            this.age = age;
            this.sex = sex;
            this.email = email;
        }
    
        @Override
        public String toString() {
            return "User{" +
                    "id=" + id +
                    ", username='" + username + '\'' +
                    ", password='" + password + '\'' +
                    ", age=" + age +
                    ", sex='" + sex + '\'' +
                    ", email='" + email + '\'' +
                    '}';
        }
    
        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 getPassword() {
            return password;
        }
    
        public void setPassword(String password) {
            this.password = password;
        }
    
        public Integer getAge() {
            return age;
        }
    
        public void setAge(Integer age) {
            this.age = age;
        }
    
        public String getSex() {
            return sex;
        }
    
        public void setSex(String sex) {
            this.sex = sex;
        }
    
        public String getEmail() {
            return email;
        }
    
        public void setEmail(String email) {
            this.email = email;
        }
    }
    

    3.创建mapper接口替代dao功能:本项目中将所有的mapper接口放在同一目录mapper下。

    package org.example.mapper;
    public interface UserMapper {
        //添加用户信息
        int insertUser();
    }
    

    1.2.4创建MyBatis映射文件

      相关概念:ORM(Object Relationship Mapping 对象映射文件)

    • 对象:Java的实体类对象。
    • 关系:关系型数据库。
    • 映射:二者之间的对应关系。

    在这里插入图片描述
      映射文件的命名规则:表所对应的实体类名+Mapper.xml,如表t_user映射实体类为User,则对应映射文件名为UserMapper.xml。因此,一个映射文件对应一个实体类,对应一张表的操作。创建映射文件(可从官方文档获取模板):

    
    DOCTYPE mapper
            PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN"
            "https://mybatis.org/dtd/mybatis-3-mapper.dtd">
    
    <mapper namespace="org.example.mapper.UserMapper">
        
        
        <insert id="insertUser">
            insert into table_user values(null,'admin','123456',23,'男','123456@qq.com')
        insert>
    mapper>
    

    注意,MyBatis面向接口编程的两个一致:

    • 1.映射文件的namespace要和mapper接口的全类名保持一致。
    • 2.映射文件中SQL语句的id要和mapper接口中的方法名一致。

      创建mapper映射文件后需在mybatis-config.xml中引入该配置文件:

    
    <mappers>
        <mapper resource="mappers/UserMapper.xml"/>
    mappers>
    

    1.2.5实现增加功能

      MyBatis中提供了操作数据库的会话对象SqlSession:

    package org.example;
    
    import org.apache.ibatis.io.Resources;
    import org.apache.ibatis.session.SqlSession;
    import org.apache.ibatis.session.SqlSessionFactory;
    import org.apache.ibatis.session.SqlSessionFactoryBuilder;
    import org.example.mapper.UserMapper;
    import org.junit.jupiter.api.Test;
    
    import java.io.IOException;
    import java.io.InputStream;
    
    public class testMyBatis {
        @Test
        public void UserTest() throws IOException {
            //1.加载核心配置文件
            InputStream inputStream=Resources.getResourceAsStream("mybatis-config.xml");
            //2.获取SqlSessionFactoryBuilder(提供SqlSession工厂对象的构建对象)
            SqlSessionFactoryBuilder sqlSessionFactoryBuilder=new SqlSessionFactoryBuilder();
            //3.通过核心配置文件对应的字节输入流创建工厂对象sqlSessionFactory,生产SqlSession对象
            SqlSessionFactory sqlSessionFactory=sqlSessionFactoryBuilder.build(inputStream);
            //4.获取SqlSession对象,此时通过SqlSession对象所操作的sql都必须手动提交或回滚事务
            //SqlSession sqlSession=sqlSessionFactory.openSession();
            //4.在创建时输入参数true,之后操作的sql都会自动提交
            SqlSession sqlSession=sqlSessionFactory.openSession(true);
            //5.通过代理模式创建UserMapper接口的代理实现类对象
            UserMapper userMapper=sqlSession.getMapper(UserMapper.class);
            //6.调用UserMapper接口中的方法,就可根据UserMapper的全类名匹配元素文件,并通过调用的方法名匹配映射文件中的SQL标签、执行SQL语句
            int result= userMapper.insertUser();//自动完成提交
            System.out.println(result);
        }
    }
    

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

    • SQLSession:代表Java程序和数据库之间的会话。
    • SqLSessionFactory:生产SQLSession的工厂。
    • 工厂模式:若要创建某一对象切使用的过程基本固定,则可将创建该对象的相关代码封装到一个工程类中,之后使用该工厂类来生产所需的对象。

    1.3整合log4j

      在src/main/resources下加入log4j配置文件log4j.properties

    #声明日志的输出级别及输出方式
    log4j.rootLogger=DEBUG,stdout
    # MyBatis logging configuration...
    # MyBatis 日志配置
    log4j.logger.org.mybatis.example.BlogMapper=TRACE
    # Console output...
    #声明日志的输出位置在控制台输出
    log4j.appender.stdout=org.apache.log4j.ConsoleAppender
    log4j.appender.stdout.layout=org.apache.log4j.PatternLayout
    #定义日志的打印格式  %t 表示线程名称  %5p表示输出日志级别   %n表示换行
    log4j.appender.stdout.layout.ConversionPattern=%5p [%t] - %m%n
    

    引入相关依赖:

    
    <dependency>
        <groupId>log4jgroupId>
        <artifactId>log4jartifactId>
        <version>1.2.17version>
    dependency>
    

    1.4修改与删除功能

    1.修改功能
      在mapper接口中增加update方法:

    package org.example.mapper;
    public interface UserMapper {
        //修改用户信息
        void updateUser();
    }
    

      修改mapper映射文件:

    
    DOCTYPE mapper
            PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN"
            "https://mybatis.org/dtd/mybatis-3-mapper.dtd">
    <mapper namespace="org.example.mapper.UserMapper">
        
        <update id="updateUser">
            update table_user set name='张三' where id=4
        update>
    mapper>
    

      进行测试:

    @Test
    public void testUpdate() throws IOException {
        InputStream inputStream=Resources.getResourceAsStream("mybatis-config.xml");
        SqlSessionFactory sqlSessionFactory=new SqlSessionFactoryBuilder().build(inputStream);
        SqlSession sqlSession=sqlSessionFactory.openSession(true);
        UserMapper userMapper=sqlSession.getMapper(UserMapper.class);
        userMapper.updateUser();
    }
    

    在这里插入图片描述
    2.删除功能
      mapper接口:

    package org.example.mapper;
    public interface UserMapper {
        //删除用户信息
        void deleteUser();
    }
    

      mapper映射文件:

    
    DOCTYPE mapper
            PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN"
            "https://mybatis.org/dtd/mybatis-3-mapper.dtd">
    <mapper namespace="org.example.mapper.UserMapper">
        
        <delete id="deleteUser">
            delete from table_user where id=5;
        delete>
    mapper>
    

      进行测试:

    @Test
    public void testDelete() throws IOException {
        InputStream inputStream=Resources.getResourceAsStream("mybatis-config.xml");
        SqlSessionFactory sqlSessionFactory=new SqlSessionFactoryBuilder().build(inputStream);
        SqlSession sqlSession=sqlSessionFactory.openSession(true);
        UserMapper userMapper=sqlSession.getMapper(UserMapper.class);
        userMapper.deleteUser();
    }
    

    在这里插入图片描述

    1.5查询功能

      使用查询功能时应明确查询结果的类型,可能是实体类对象、实体类对象的集合、单列数据等。

    1.5.1查询单个实体类对象

      mapper接口中声明方法:

    package org.example.mapper;
    import org.example.Pojo.User;
    public interface UserMapper {
        //根据id查询用户信息
        User getUserById();
    }
    

      修改mapper映射文件,由于返回值是实体类类型,故需使用resultType进行声明:

    
    DOCTYPE mapper
            PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN"
            "https://mybatis.org/dtd/mybatis-3-mapper.dtd">
    <mapper namespace="org.example.mapper.UserMapper">
        
        <select id="getUserById" resultType="org.example.Pojo.User">
            select * from table_user where id=3
        select>
    mapper>
    
    • resultType:设置默认的映射关系。得到单行的查询结果后,会自动将结果的字段名作为属性名并进行赋值,无法匹配则不赋值(本例中表中name与实体类属性username无法映射自动赋值,故为null)。
    • resultMap:设置自定义的映射关系(后文中有详解)。
        进行测试:
    @Test
    public void testSelect() throws IOException {
        InputStream inputStream=Resources.getResourceAsStream("mybatis-config.xml");
        SqlSessionFactory sqlSessionFactory=new SqlSessionFactoryBuilder().build(inputStream);
        SqlSession sqlSession=sqlSessionFactory.openSession(true);
        UserMapper userMapper=sqlSession.getMapper(UserMapper.class);
        User user=userMapper.getUserById();
        System.out.println(user);
    }
    

    在这里插入图片描述

    1.5.2查询所有用户信息

      mapper接口中声明方法:

    package org.example.mapper;
    import org.example.Pojo.User;
    import java.util.List;
    public interface UserMapper {
        //查询所有用户信息
        List<User> getAllUser();
    }
    

      修改mapper映射文件:

    
    DOCTYPE mapper
            PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN"
            "https://mybatis.org/dtd/mybatis-3-mapper.dtd">
    <mapper namespace="org.example.mapper.UserMapper">
        
        <select id="getAllUser" resultType="org.example.Pojo.User">
            select * from table_user;
        select>
    mapper>
    

      进行测试:

    @Test
    public void testSelect() throws IOException {
        InputStream inputStream=Resources.getResourceAsStream("mybatis-config.xml");
        SqlSessionFactory sqlSessionFactory=new SqlSessionFactoryBuilder().build(inputStream);
        SqlSession sqlSession=sqlSessionFactory.openSession(true);
        UserMapper userMapper=sqlSession.getMapper(UserMapper.class);
        List<User> list=userMapper.getAllUser();
        System.out.println(list);
    }
    

    在这里插入图片描述

    二、核心配置文件详解

      核心配置文件中的标签必须按固定的顺序:
      propertiessettingstypeAliasestypeHandlersobjectFactoryobjectWrapperFactoryreflectorFactorypluginsenvironmentsdatabaseIdProvidermapper

    
    DOCTYPE configuration
      PUBLIC "-//mybatis.org//DTD Config 3.0//EN"
      "https://mybatis.org/dtd/mybatis-3-config.dtd">
    <configuration>
    	
      <environments default="development">
        <environment id="development">
          <transactionManager type="JDBC"/>
          <dataSource type="POOLED">
            <property name="driver" value="${driver}"/>
            <property name="url" value="${url}"/>
            <property name="username" value="${username}"/>
            <property name="password" value="${password}"/>
          dataSource>
        environment>
      environments>
      
      <mappers>
        <mapper resource="org/mybatis/example/BlogMapper.xml"/>
      mappers>
    configuration>
    

    2.1environments

      是复数标签,故而可配置多个连接数据库的环境,有属性default,用于指定默认使用的环境(使用mybatis创建SqlSessionFactory对象未指定环境时使用的环境,一般一个数据库只会对应一个SqlSessionFactory对象),值为标签的id值。而标签用于配置某个具体的环境,其id属性是该环境的唯一标识,不能重复。标签有以下子标签:

    • :使用唯一属性type设置事务管理方式,且有如下两种取值:
      • MANAGED:mybatis不再负责事务的管理了。事务交给其他容器来负责,如spring。当前是单纯的mybatis环境,事务不被任何机制负责,则事务功能关闭。
      • JDBC:执行SQL时使用JDBC中原生的事务管理方式,即,默认开启事务,且事务的提交与回滚需要手动处理。可使用以下方式关闭事务:
    SqlSession sqlSession = sqlSessionFactory.openSession(true);  //关闭事务,转为自动提交
    
    • :为程序提供Connection对象,一般为程序提供Connection对象的称为数据源。数据源是一种规范,JDK中提供了javax.sql.DataSource接口作为数据源规范,可通过实现接口来定义数据源。类似的,数据库连接池也是提供连接对象的,故所有数据库连接池都是数据源,如druid、c3p0、dbcp等。标签有唯一属性type,用于指定数据源类型,共有三种取值:
      • UNPOOLED:不使用数据库连接池技术。每一次请求过来之后,都是创建新的Connection对象。
      • POOLED:使用mybatis自己的数据库连接池技术。
      • JNDI:集成第三方的数据库连接池。JNDI是一套规范。大部分 Web 容器,如tomcat、jetty等都实现了 JNDI 规范。
    • 的子标签,用于配置属性(键值对)。

      注意,当type属性值不同时,可使用的子标签也不同,参考官方文档:

    1.UNPOOLED
    在这里插入图片描述
    2.POOLED
    在这里插入图片描述
    3.JDNI
    在这里插入图片描述
    在这里插入图片描述

    2.2properties

      是复数标签,可使用子标签配置属性(键值对,配置方式同下的标签),也可引用外部配置文件进行配置。在同级目录下创建配置文件db.properties

    jdbc.driver=com.mysql.cj.jdbc.Driver
    jdbc.url=jdbc:mysql://localhost:3306/testdatabase?serverTimezone=Asia/Shanghai&useUnicode=true&characterEncoding=utf8&useSSL=true
    jdbc.username=root
    jdbc.password=123456
    
    • 在核心配置文件中使用属性resource指定同级目录下(类路径下)的配置文件db.properties
    
    DOCTYPE configuration
            PUBLIC "-//mybatis.org//DTD Config 3.0//EN"
            "https://mybatis.org/dtd/mybatis-3-config.dtd">
    <configuration>
        <properties resource="db.properties"/>
        <environments default="development">
            <environment id="development">
                <transactionManager type="JDBC"/>
                <dataSource type="POOLED">
                    <property name="driver" value="${jdbc.driver}"/>
                    <property name="url" value="${jdbc.url}"/>
                    <property name="username" value="${jdbc.username}"/>
                    <property name="password" value="${jdbc.password}"/>
                dataSource>
            environment>
        environments>
    configuration>
    
    • 当不在同一类路径下时,需使用url属性,使用绝对路径来指定文件。事实上,平时使用的文件路径都是基于file协议的,只是Windows文件夹系统的文件夹省略了,使用时需加上file///,如:
    <properties resource="file\\\C:\Users\28591\IDEA\myProjects\Spring6\spring-first\src\main\resources\db.properties"/>
    

    配置文件优先级:当一个属性在不止一个地方进行了配置,则MyBatis按照下列顺序进行加载:

    • 首先读取在 properties 元素体内指定的属性。
    • 然后根据 properties 元素中的 resource 属性读取类路径下属性文件,或根据 url 属性指定的路径读取属性文件,并覆盖之前读取过的同名属性。
    • 最后读取作为方法参数传递的属性,并覆盖之前读取过的同名属性。

    由此,通过方法参数传递的属性具有最高优先级,resource/url 属性中指定的配置文件次之,最低优先级的则是 properties 元素中指定的属性。

    2.3typeAliases

      myBatis提供了来设置类型别名,其含有子标签

    • :设置类型别名,含有属性type、alias。指定后,可在