• MyBatis学习笔记(2022-11-30)


    在这里插入图片描述

    熬过无人问津的日子才会有诗和远方。


    一、MyBatis简述


    • MyBatis 是一款优秀的持久层框架,用于简化JDBC开发。(半自动化的ORM框架)
    • 它支持自定义SQL、存储过程以及高级映射。
    • MyBatis 可以使用简单的 XML 或注解来配置和映射原生信息,将接口和Java的POJOs(Plain Ordinary Java Object,普通的Java对象)映射成数据库中的记录。
    • MyBatis 是 Apache的一个开源项目iBatis,在2010年6月 Apache 将项目交与Google进行管理,更名MyBatis。于2013年11月迁移到GitHub上。
    • Mybatis官网:https://mybatis.org/mybatis-3/zh/index.html
    • 项目地址:https://github.com/mybatis/mybatis-3/releases
    • 目前最新版本是:3.5.11,其发布时间是2022年9月18日。

    什么是框架?

    • 框架就是一个半成品软件,是一套可重用的、通用的、软件基础代码模型。
    • 在框架的基础之上构建软件编写更加高效、规范、通用、可扩展。

    三层架构和SSM框架的关系

    三层架构:数据访问层、业务逻辑层和表示层(web层),区分层次的目的即为了高内聚低耦合的思想。在软件体系架构设计中,分层式结构是最常见,也是最重要的一种结构。

    MVC:模型(model)、视图(view)、控制器(controller。

    SSM:Spring Framework、Spring MVC、MyBatis(扩展MyBatis-Plus)。

    SSH:Spring、Struts、Hibernate(扩展JPA)。

    JavaSE => JDBC => Servlet+JSP => SSM =>SpringBoot(分布式) => SpringCould(微服务)


    MyBatis缺点

    • 编写SQL语句时工作量很大,尤其是字段多、关联表多时,更是如此。
    • SQL语句依赖于数据库,导致数据库移植性差,不能更换数据库。
    • 框架还是比较简陋,功能尚有缺失,虽然简化了数据绑定代码,但是整个底层数据库查询实际还是要自己写的,工作量也比较大,而且不太容易适应快速数据库修改。
    • 二级缓存机制不佳。

    软件设计:(open-close开闭原则)尽量不修改源代码,对程序进行扩展。

    • 对扩展是开放的。
    • 对修改源码是关闭的。

    如何使用MyBatis?

    1、使用 MyBatis, 只需将 mybatis-x.x.x.jar 文件置于类路径(classpath)中即可。

    2、如果使用 Maven 来构建项目,则需将下面的依赖引入 pom.xml 文件中:

    <dependency>
      <groupId>org.mybatisgroupId>
      <artifactId>mybatisartifactId>
      <version>x.x.xversion>
    dependency>
    
    • 1
    • 2
    • 3
    • 4
    • 5



    二、快速入门


    通过本节可以初步了解MyBatis的使用以及logback的配置

    1、创建一个普通的Maven项目

    2、引入依赖坐标

    
    <dependency>
        <groupId>org.mybatisgroupId>
        <artifactId>mybatisartifactId>
        <version>3.5.5version>
    dependency>
    
    <dependency>
        <groupId>mysqlgroupId>
        <artifactId>mysql-connector-javaartifactId>
        <version>5.1.46version>
    dependency>
    
    <dependency>
        <groupId>junitgroupId>
        <artifactId>junitartifactId>
        <version>4.12version>
        <scope>testscope>
    dependency>
    
    <dependency>
        <groupId>org.slf4jgroupId>
        <artifactId>slf4j-apiartifactId>
        <version>1.7.20version>
    dependency>
    
    <dependency>
        <groupId>ch.qos.logbackgroupId>
        <artifactId>logback-classicartifactId>
        <version>1.2.3version>
    dependency>
    
    <dependency>
        <groupId>ch.qos.logbackgroupId>
        <artifactId>logback-coreartifactId>
        <version>1.2.3version>
    dependency>
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27
    • 28
    • 29
    • 30
    • 31
    • 32
    • 33
    • 34
    • 35
    • 36
    • 37

    在这里插入图片描述


    3、导入SQL脚本

    -- 创建数据库
    drop database if exists `mybatis`;
    create database `mybatis` character set = utf8;
    
    use mybatis;
    
    -- 创建数据表
    create table `user`(
    	`id` int auto_increment primary key comment '编号',
    	`name` varchar(20) unique comment '姓名', -- 唯一约束
    	`pwd` varchar(20) comment '密码',
    	`gender` char(1) comment '性别',
    	`addr` varchar(30) comment '家庭住址'
    )engine=innodb default charset=utf8;
    
    -- 插入数据
    insert into user(name,pwd,gender,addr) values
    ("张三","123456",'男',"北京"),
    ("李四","123456",'女',"南京"),
    ("王五","777777",'男',"杭州"),
    ("赵六","123456",'女',"温州"),
    ("陈七","666666",'男',"黑河");
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22

    在这里插入图片描述


    4、编写实体类

    package com.baidou.pojo;
    
    /**
     * 用户实体类
     *
     * @author 白豆五
     * @version 2022/11/30 11:07
     * @since JDK8
     */
    public class User {
        private Integer id;  // 编号
        private String name; // 姓名
        private String pwd;  // 密码
        private char gender; // 性别
        private String addr; // 家庭住址
    
        // 满参构造方法
        public User(Integer id, String name, String pwd, char gender, String addr) {
            this.id = id;
            this.name = name;
            this.pwd = pwd;
            this.gender = gender;
            this.addr = addr;
        }
    
        // 无参构造方法
        public User() {
        }
    
        // set/get方法
        public Integer getId() {
            return id;
        }
    
        public void setId(Integer id) {
            this.id = id;
        }
    
        public String getName() {
            return name;
        }
    
        public void setName(String name) {
            this.name = name;
        }
    
        public String getPwd() {
            return pwd;
        }
    
        public void setPwd(String pwd) {
            this.pwd = pwd;
        }
    
        public char getGender() {
            return gender;
        }
    
        public void setGender(char gender) {
            this.gender = gender;
        }
    
        public String getAddr() {
            return addr;
        }
    
        public void setAddr(String addr) {
            this.addr = addr;
        }
    
        
        // 重写Object类的toString方法,返回对象里的内容
        // Object类的toString方法返回的是对象的地址值,即: "类的全限定名@十六进制的哈希码"
        @Override
        public String toString() {
            return "User{" +
                    "id=" + id +
                    ", name='" + name + '\'' +
                    ", pwd='" + pwd + '\'' +
                    ", gender=" + gender +
                    ", addr='" + addr + '\'' +
                    '}';
        }
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27
    • 28
    • 29
    • 30
    • 31
    • 32
    • 33
    • 34
    • 35
    • 36
    • 37
    • 38
    • 39
    • 40
    • 41
    • 42
    • 43
    • 44
    • 45
    • 46
    • 47
    • 48
    • 49
    • 50
    • 51
    • 52
    • 53
    • 54
    • 55
    • 56
    • 57
    • 58
    • 59
    • 60
    • 61
    • 62
    • 63
    • 64
    • 65
    • 66
    • 67
    • 68
    • 69
    • 70
    • 71
    • 72
    • 73
    • 74
    • 75
    • 76
    • 77
    • 78
    • 79
    • 80
    • 81
    • 82
    • 83
    • 84

    在这里插入图片描述

    5、编写mapper接口

    package com.baidou.mapper;
    
    import com.baidou.pojo.User;
    
    import java.util.List;
    
    /**
     * 基于MyBatis实现用户接口
     * mapper、dao都是对数据库进行持久化操作的(crud)
     */
    public interface UserMapper {
        // 查询所有用户
        List<User> selectAll();
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14

    在这里插入图片描述

    6、编写UserMapper.xml(SQL映射文件)

    参考MyBatis官网的入门案例:https://mybatis.org/mybatis-3/zh/getting-started.html

    在这里插入图片描述

    在这里插入图片描述

     
    DOCTYPE mapper
            PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN"
            "https://mybatis.org/dtd/mybatis-3-mapper.dtd">
    
    
    
    
    <mapper namespace="com.baidou.mapper.UserMapper">
        
        <select id="selectAll" resultType="com.baidou.pojo.User">
            select * from user
        select>
    mapper>
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26

    7、编写MyBatis核心配置文件

    参考MyBatis官网的入门案例:https://mybatis.org/mybatis-3/zh/getting-started.html

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

    
    DOCTYPE configuration
            PUBLIC "-//mybatis.org//DTD Config 3.0//EN"
            "http://mybatis.org/dtd/mybatis-3-config.dtd">
    
    
    <configuration>
        
        <environments default="development">
        	
            <environment id="development">
                
                <transactionManager type="JDBC"/>
                
                <dataSource type="POOLED">
                    <property name="driver" value="com.mysql.jdbc.Driver"/>
                    <property name="url"
                              value="jdbc:mysql://127.0.0.1:3306/mybatis?useSSL=false&useUnicode=true&characterEncoding=UTF-8"/>
                    <property name="username" value="root"/>
                    <property name="password" value="123456"/>
                dataSource>
            environment>
        environments>
    
        
        <mappers>
            
            <mapper resource="com/baidou/mapper/UserMapper.xml"/>
        mappers>
    configuration>
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27
    • 28
    • 29
    • 30
    • 31
    • 32

    8、编写logback.xml日志配置文件

    在这里插入图片描述

    <?xml version="1.0" encoding="UTF-8"?>
    <!-- 配置文件修改时重新加载,默认true -->
    <configuration scan="true">
    
        <!--控制台输出-->  
        <appender name="Console" class="ch.qos.logback.core.ConsoleAppender">                
            <encoder> 
                <!-- 输出的日志格式 -->
                <pattern>[%level] %blue(%d{HH:mm:ss.SSS}) %cyan([%thread]) %boldGreen(%logger{15}) - %msg%n</pattern>   
            </encoder>    
        </appender>
    
        <!--level:用来设置日志输出级别,OFF FATAL ERROR WARN INFO DEBUG TRACE ALL,默认DEBUG-->
        <logger name="com.baidou" level="DEBUG" additivity="false">
            <appender-ref ref="Console"/>
        </logger>
        <root level="DEBUG">
            <appender-ref ref="Console"/>
        </root>
    </configuration>
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20

    9、编写测试

    import com.baidou.mapper.UserMapper;
    import com.baidou.pojo.User;
    import org.apache.ibatis.io.Resources;
    import org.apache.ibatis.session.SqlSession;
    import org.apache.ibatis.session.SqlSessionFactory;
    import org.apache.ibatis.session.SqlSessionFactoryBuilder;
    import org.junit.Test;
    
    import java.io.IOException;
    import java.io.InputStream;
    import java.util.List;
    
    /**
     * mybatis快速入门
     * @author 白豆五
     * @version 2022/11/30 12:55
     * @since JDK8
     */
    public class MyTest {
    
        /**
         * 方式一: 使用qlSession.selectList()查询所有用户(旧版mybatis的API,不推荐使用)
         * @throws IOException
         */
        @Test
        public void test1() throws IOException {
            // 1、加载mybatis核心配置文件,获取SqlSessionFactory对象
            String resource = "mybatis-config.xml";
            InputStream is = Resources.getResourceAsStream(resource);
            SqlSessionFactory sqlSessionFactory = new SqlSessionFactoryBuilder().build(is);
    
            // 2、获取对应的SqlSession对象,用来执行sql语句
            SqlSession sqlSession = sqlSessionFactory.openSession();
            // 3、执行sql语句,  selectList()方法的参数是一个字符串,该字符串必须是映射配置文件的 namespace.id
            List<User> list = sqlSession.selectList("com.baidou.mapper.UserMapper.selectAll");
            // 输出结果
            for (User user :
                    list) {
                System.out.println(user);
            }
            // 4、释放资源
            sqlSession.close();
        }
    
        /**
         * 使用Mapper代理开发,查询所有用户
         * @throws IOException
         */
        @Test
        public void test2() throws IOException {
            // 1、加载Mybatis核心配置文件,获取SqlSessionFactory对象
            InputStream inputStream = Resources.getResourceAsStream("mybatis-config.xml");
            SqlSessionFactory sqlSessionFactory = new SqlSessionFactoryBuilder().build(inputStream);
            // 2、获取对应的SqlSession对象,用来执行sql语句
            SqlSession sqlSession = sqlSessionFactory.openSession();
            // 3、获取mapper,来调用mapper中的方法
            UserMapper mapper = sqlSession.getMapper(UserMapper.class);
            List<User> users = mapper.selectAll();
            users.forEach(System.out::println);
            // 4、关闭SqlSession
            sqlSession.close();
        }
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27
    • 28
    • 29
    • 30
    • 31
    • 32
    • 33
    • 34
    • 35
    • 36
    • 37
    • 38
    • 39
    • 40
    • 41
    • 42
    • 43
    • 44
    • 45
    • 46
    • 47
    • 48
    • 49
    • 50
    • 51
    • 52
    • 53
    • 54
    • 55
    • 56
    • 57
    • 58
    • 59
    • 60
    • 61
    • 62
    • 63

    test1()方法执行结果:
    在这里插入图片描述

    test2()方法执行结果:
    在这里插入图片描述

    • 第一种方式:sqlSession.selectList(),属于方法的调用(mybatis旧版的api),需要传入映射文件的名称空间和查询语句的id(即 "namespace.id"),然后它每次返回的类型都是Object,会存在类型转换问题,导致不太安全。
    • 第二种方式:sqlSession.getMapper(),更灵活的使用方法,不依赖上述的字符串字面值而且安全,只需传参UserMapper.class,返回的是mapper接口的代理对象,然后通过mapper调用对应方法完成sql的执行。

    官网解释:
    在这里插入图片描述

    MyBatis执行流程:

    在这里插入图片描述
    总结:

    • 导入MyBatis依赖
    • 编写核心配置文件,mybatis-config.xml
    • 编写实体、接口
    • 编写mapper.xml(mapper接口 对应mapper.xml)
    • 在核心配置文件中注册这个mapper.xml
    • 编写工具类(用来获取SqlSession实例)
    • 通过工具类得到SqlSession,然后通过SqlSession来获取mapper代理对象,之后通过这个mapper来调用它的方法
    • 关闭SqlSession



    三、MyBatis配置文件详解


    MyBatis核心配置文件:mybatis-config.xml

    MyBatis映射配置文件:XxxMapper.xml

    后期在使用MyBatis框架做数据库操作(持久化操作)会经常使用这两个配置文件。

    当然我们也可以在这个XML的dtd约束文件中查看相应的配置:

    在这里插入图片描述


    1. MyBatis核心配置文件


    核心配置文件(mybatis-config.xml)的层级结构如下:

    在这里插入图片描述

    注:配置每个标签时,需要遵守前后顺序!


    1.1 configuration(配置)


    configuration表示核心配置文件的根标签。

    在这里插入图片描述


    1.2 properties(属性)


    • properties属性可以引用外部配置文件;
    • properties属性也可以在内部增加一些属性配置;
    • 如果两个文件有共同的字段,会优先使用外部配置文件的!

    1、编写db.properties配置文件

    driver=com.mysql.jdbc.Driver
    url=jdbc:mysql://localhost:3306/mybatis?useSSL=false&useUnicode=true&characterEncoding=utf-8
    username=root
    password=123456
    
    • 1
    • 2
    • 3
    • 4

    2、在mybatis-config.xml中引用db.properties

    
    DOCTYPE configuration
            PUBLIC "-//mybatis.org//DTD Config 3.0//EN"
            "http://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="${driver}"/>
                    <property name="url" value="${url}"/>
                    <property name="username" value="${username}"/>
                    <property name="password" value="${password}"/>
                dataSource>
            environment>
        environments>
    
        
        <mappers>
            
            <package name="com.baidou.mapper"/>
        mappers>
    configuration>
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27
    • 28

    1.3 environments(环境配置)


    • MyBatis 可以配置多种环境,但每个 SqlSessionFactory 实例只能选择一种环境;
    • 用ID这个唯一标识来切换默认使用的环境,如开发环境、测试环境、生产环境/线上;
    • MyBatis默认的事务管理器是JDBC,后期在Spring中会替换成声明式事务;
    • MyBatis默认连接池是POOLED,后期我们可以使用第三方数据库连接池(如Druid、C3P0等)。

    在这里插入图片描述

    在公司做项目的时候,如果开发阶段连接开发环境的数据库,那么数据库的配置要管运维或者DBA的同事要。


    1.4 typeAliases(类型别名)


    类型别名可为 Java 类型设置一个缩写名字。 它仅用于 XML 配置,意在降低冗余的全限定类名书写;

    使用场景:1、给实体类起别名(跟map挺像,K-V键值对)

    <typeAliases>
        <typeAlias type="com.baidou.pojo.User" alias="user"/>
    typeAliases>
    
    • 1
    • 2
    • 3

    使用场景:2、扫描实体类的包,它的的默认别名为类名,首字母小写

    <typeAliases>
        <package name="com.baidou.pojo"/>
    typeAliases>
    
    • 1
    • 2
    • 3

    在实体类比较少的时候使用第一种方式,如果实体类比较多建议使用第二种方式!

    区别:第一种可以自定义别名,第二种它就不行(如果非要改 需要在实体类上增加@Alias注解)。


    下面是一些为常见的 Java 类型内建的类型别名。它们都是不区分大小写的,注意,为了应对原始类型的命名重复,采取了特殊的命名风格。

    别名映射的类型
    _bytebyte
    _longlong
    _shortshort
    _intint
    _integerint
    _doubledouble
    _floatfloat
    _booleanboolean
    stringString
    byteByte
    longLong
    shortShort
    intInteger
    integerInteger
    doubleDouble
    floatFloat
    booleanBoolean
    dateDate
    decimalBigDecimal
    bigdecimalBigDecimal
    objectObject
    mapMap
    hashmapHashMap
    listList
    arraylistArrayList
    collectionCollection
    iteratorIterator

    1.5 settings(设置)


    在MyBatis全局配置文件中通过标签控制MyBatis全局开关。

    MyBatis的设置:https://mybatis.org/mybatis-3/zh/configuration.html#settings

    在这里插入图片描述


    示例:在mybatis-config.xml配置日志输出

    <settings>
        <setting name="logImpl" value="STDOUT_LOGGING"/>
    settings>
    
    • 1
    • 2
    • 3

    1.6 mappers(映射器)


    mappers(映射器)的作用是告诉 MyBatis 到哪里去找映射文件;

    使用场景:1. 使用相对于类路径的资源引用(推荐使用)

    
    <mappers>
      <mapper resource="org/mybatis/builder/AuthorMapper.xml"/>
      <mapper resource="org/mybatis/builder/BlogMapper.xml"/>
      <mapper resource="org/mybatis/builder/PostMapper.xml"/>
    mappers>
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6

    使用场景:2. 使用映射器接口实现类绑定注册

    <mappers>
      <mapper class="org.mybatis.builder.AuthorMapper"/>
      <mapper class="org.mybatis.builder.BlogMapper"/>
      <mapper class="org.mybatis.builder.PostMapper"/>
    mappers>
    
    • 1
    • 2
    • 3
    • 4
    • 5

    使用场景:3. 使用包扫描进行注入绑定

    <mappers>
      <package name="org.mybatis.builder"/>
    mappers>
    
    • 1
    • 2
    • 3

    注:接口和它的配置文件必须同名,接口和它的映射文件必须在同级包下(SQL映射文件可以放在src目录中,也可以放在resources目录中 );


    1.7 其它配置


    • typeHandlers(类型处理器)
    • objectFactory(对象工厂)
    • plugins(插件)
    • databaseIdProvider(数据库厂商标识)

    2. MyBatis映射配置文件


    MyBatis 真正强大之处在于它的语句映射,这是它的魔力所在。由于它的功能强大,映射器的 XML 文件就显得相对简单。如果拿它跟具有相同功能的 JDBC 代码进行对比,你会立即发现省掉了将近 95% 的代码。MyBatis 致力于减少使用成本,让用户能更专注于写SQL代码😥。

    SQL 映射配置文件标签结构如下:

    • mapper – 作为映射配置文件的根标签,namespace属性值就是绑定mapper接口的全限定名(包名.接口名)。
      • cache – 该命名空间的缓存配置。
      • cache-ref – 引用其它命名空间的缓存配置。
      • resultMap – 描述如何从数据库结果集中加载对象,是最复杂也是最强大的元素。
      • parameterMap – 老式风格的参数映射。此元素已被废弃,并可能在将来被移除!请使用行内参数映射。文档中不会介绍此元素。
      • sql – 可被其它语句引用的可重用语句块。
      • select – 映射查询语句,resultType – SQL语句执行的返回值;parameterType – 参数类型;
      • insert – 映射插入语句。
      • update – 映射更新语句。
      • delete – 映射删除语句。

    在mapper接口中定义方法,方法名就是该SQL映射文件中sql语句的id,并保持参数类型和返回值类型一致;

    在这里插入图片描述



    四、CRUD操作


    使用MyBatis针对User表实现增删改查操作以及工具类的使用。

    前期准备:配置数据库资源文件db.properties以及MyBatis核心配置文件。

    sql脚本:

    -- 创建数据库
    drop database if exists `mybatis`;
    create database `mybatis` character set = utf8;
    
    use mybatis;
    
    -- 创建数据表
    create table `user`(
    	`id` int auto_increment primary key comment '编号',
    	`name` varchar(20) unique comment '姓名', -- 唯一约束
    	`pwd` varchar(20) comment '密码',
    	`gender` char(1) comment '性别',
    	`addr` varchar(30) comment '家庭住址'
    )engine=innodb default charset=utf8;
    
    -- 插入数据
    insert into user(name,pwd,gender,addr) values
    ("张三","123456",'男',"北京"),
    ("李四","123456",'女',"南京"),
    ("王五","777777",'男',"杭州"),
    ("赵六","123456",'女',"温州"),
    ("陈七","666666",'男',"黑河");
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22

    db.properties:

    db.driver=com.mysql.jdbc.Driver
    db.url=jdbc:mysql://127.0.0.1:3306/mybatis?useSSL=false&useUnicode=true&acharacterEncoding=UTF-8
    db.username=root
    db.password=123456
    
    • 1
    • 2
    • 3
    • 4

    mybatis-config.xml:

    
    DOCTYPE configuration
            PUBLIC "-//mybatis.org//DTD Config 3.0//EN"
            "http://mybatis.org/dtd/mybatis-3-config.dtd">
    
    <configuration>
        
        <properties resource="db.properties"/>
    
        
        <typeAliases>
            <package name="com.baidou.pojo"/>
        typeAliases>
    
        
        <environments default="dev">
            <environment id="dev">
                <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>
            
            <package name="com.baidou.mapper"/>
        mappers>
    configuration>
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27
    • 28
    • 29
    • 30
    • 31
    • 32
    • 33

    1. 使用MyBatis实现查询用户


    1、编写实体类

    package com.baidou.pojo;
    
    /**
     * 用户实体类
     *
     * @author 白豆五
     * @version 2022/11/30 11:07
     * @since JDK8
     */
    public class User {
        private Integer id;  // 编号
        private String name; // 姓名
        private String pwd;  // 密码
        private char gender; // 性别
        private String addr; // 家庭住址
    
        // 满参构造方法
        public User(Integer id, String name, String pwd, char gender, String addr) {
            this.id = id;
            this.name = name;
            this.pwd = pwd;
            this.gender = gender;
            this.addr = addr;
        }
    
        // 无参构造方法
        public User() {
        }
    
        // set/get方法
        public Integer getId() {
            return id;
        }
    
        public void setId(Integer id) {
            this.id = id;
        }
    
        public String getName() {
            return name;
        }
    
        public void setName(String name) {
            this.name = name;
        }
    
        public String getPwd() {
            return pwd;
        }
    
        public void setPwd(String pwd) {
            this.pwd = pwd;
        }
    
        public char getGender() {
            return gender;
        }
    
        public void setGender(char gender) {
            this.gender = gender;
        }
    
        public String getAddr() {
            return addr;
        }
    
        public void setAddr(String addr) {
            this.addr = addr;
        }
    
    
        // 重写toString方法
        @Override
        public String toString() {
            return "User{" +
                    "id=" + id +
                    ", name='" + name + '\'' +
                    ", pwd='" + pwd + '\'' +
                    ", gender=" + gender +
                    ", addr='" + addr + '\'' +
                    '}';
        }
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27
    • 28
    • 29
    • 30
    • 31
    • 32
    • 33
    • 34
    • 35
    • 36
    • 37
    • 38
    • 39
    • 40
    • 41
    • 42
    • 43
    • 44
    • 45
    • 46
    • 47
    • 48
    • 49
    • 50
    • 51
    • 52
    • 53
    • 54
    • 55
    • 56
    • 57
    • 58
    • 59
    • 60
    • 61
    • 62
    • 63
    • 64
    • 65
    • 66
    • 67
    • 68
    • 69
    • 70
    • 71
    • 72
    • 73
    • 74
    • 75
    • 76
    • 77
    • 78
    • 79
    • 80
    • 81
    • 82
    • 83

    2、编写接口:

    package com.baidou.mapper;
    
    import com.baidou.pojo.User;
    
    import java.util.List;
    
    /**
     * 基于MyBatis实现用户接口
     *
     */
    public interface UserMapper {
        // 根据id查询用户信息
        User findUserById(int id);
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14

    3、编写mapper映射文件:

     
    DOCTYPE mapper
            PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN"
            "https://mybatis.org/dtd/mybatis-3-mapper.dtd">
    
    <mapper namespace="com.baidou.mapper.UserMapper">
    
        
        <select id="findUserById" resultType="com.baidou.pojo.User">
            select * from user where id =#{id}
        select>
    mapper>
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • #{}表示占位符,可以看做JDBC中PreparedStatement的?占位符。(预处理)

    4、编写测试
    package com.baidou.mapper;
    
    import com.baidou.pojo.User;
    import org.apache.ibatis.io.Resources;
    import org.apache.ibatis.session.SqlSession;
    import org.apache.ibatis.session.SqlSessionFactory;
    import org.apache.ibatis.session.SqlSessionFactoryBuilder;
    import org.junit.Test;
    
    import java.io.IOException;
    import java.io.InputStream;
    
    /**
     * 测试类
     *
     * @author 白豆五
     * @version 2022/12/1 20:51
     * @since JDK8
     */
    public class UserMapperTest {
    
        @Test
        public void testFindUserById() throws IOException {
            // 加载Mybatis核心配置文件,获取SqlSessionFactory对象
            InputStream inputStream = Resources.getResourceAsStream("mybatis-config.xml");
            SqlSessionFactory sqlSessionFactory = new SqlSessionFactoryBuilder().build(inputStream);
            // 通过sqlSession工厂构建SqlSession对象
            SqlSession sqlSession = sqlSessionFactory.openSession();
            // 获取接口的mapper代理对象
            UserMapper mapper = sqlSession.getMapper(UserMapper.class);
            // 调用mapper中的方法,执行sql语句
            User user = mapper.findUserById(1);
            System.out.println(user);
            // 关闭SqlSession
            sqlSession.close();
        }
    }
    
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27
    • 28
    • 29
    • 30
    • 31
    • 32
    • 33
    • 34
    • 35
    • 36
    • 37
    • 38

    在这里插入图片描述


    2. 使用MyBatis实现添加用户


    编写接口:

    // 添加用户
    int addUser(User user);
    
    • 1
    • 2

    编写mapper映射文件:

    <!-- 添加用户-->
    <insert id="addUser" parameterType="user">
        insert into mybatis.user(name, pwd, gender, addr) values(#{name}, #{pwd}, #{gender}, #{addr});
    </insert>
    
    • 1
    • 2
    • 3
    • 4

    编写测试:

    @Test
    public void testaddUser() throws IOException {
        InputStream inputStream = Resources.getResourceAsStream("mybatis-config.xml");
        SqlSessionFactory sqlSessionFactory = new SqlSessionFactoryBuilder().build(inputStream);
        SqlSession sqlSession = sqlSessionFactory.openSession();
        UserMapper mapper = sqlSession.getMapper(UserMapper.class);
    
        User user = new User();
        user.setName("水火");
        user.setAddr("洛杉矶");
        user.setGender('男');
        user.setPwd("shuihuo123");
    
        int count = mapper.addUser(user);
        sqlSession.commit();
    
        if (count > 0) {
            System.out.println("添加成功");
        }
        sqlSession.close();
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21

    在这里插入图片描述

    因为我们配置主键是自动增加的,也就是不给主键穿值,当同时插入两张表的时候会出现问题,装进对象的时候id为null,通过如下配置解决这个问题。

    在 insert 标签上添加如下属性:

    • useGeneratedKeys:能够获取自动增长的主键值。true表示获取。
    • keyProperty :指定将获取到的主键值封装到哪儿个属性里。

    3. 使用MyBatis实现修改用户


    编写接口:

    // 修改用户
    int updateUser(User user);
    
    • 1
    • 2

    编写mapper映射文件:

    <!--修改用户-->
    <update id="updateUser" parameterType="user">
        update mybatis.user set name=#{name},pwd=#{pwd} where id=#{id}
    </update>
    
    • 1
    • 2
    • 3
    • 4

    编写测试:

    @Test
    public void testUpdateUser() throws IOException {
        InputStream inputStream = Resources.getResourceAsStream("mybatis-config.xml");
        SqlSessionFactory sqlSessionFactory = new SqlSessionFactoryBuilder().build(inputStream);
        SqlSession sqlSession = sqlSessionFactory.openSession();
        UserMapper mapper = sqlSession.getMapper(UserMapper.class);
    
        User user = new User();
        user.setId(6);
        user.setName("葛小伦");
        user.setPwd("gexiaolun");
    
        int count = mapper.updateUser(user);
        sqlSession.commit();
    
        if (count > 0) {
            System.out.println("修改成功");
        }
        sqlSession.close();
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20

    在这里插入图片描述


    4. 使用MyBatis实现删除用户


    编写接口:

    // 通过id删除用户
    int deleteUserById(int id);
    
    • 1
    • 2

    编写mapper映射文件:

    
    <delete id="deleteUserById">
        delete from user where id=#{id}
    delete>
    
    • 1
    • 2
    • 3
    • 4

    编写测试:

    @Test
    public void testDeleteUserById() throws IOException {
        InputStream inputStream = Resources.getResourceAsStream("mybatis-config.xml");
        SqlSessionFactory sqlSessionFactory = new SqlSessionFactoryBuilder().build(inputStream);
        SqlSession sqlSession = sqlSessionFactory.openSession();
        UserMapper mapper = sqlSession.getMapper(UserMapper.class);
    
        int count = mapper.deleteUserById(6);
        sqlSession.commit();
    
        if (count > 0) {
            System.out.println("删除成功");
        }
        sqlSession.close();
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15

    在这里插入图片描述
    注意:增删改需要提交事务。(mybatis默认把自动提交事务改成手动提交,可以在sqlsession.open(true)开启自动提交事务,他这个方法不传参默认是手动提交,但是不推荐直接传参,手动根据场景使用比较灵活)


    5. MyBatis工具类


    package com.baidou.util;
    
    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 java.io.IOException;
    import java.io.InputStream;
    
    /**
     * MyBatisUtils工具类
     *
     * @author 白豆五
     * @version 2022/12/1 21:32
     * @since JDK8
     */
    public class MyBatisUtils {
    
        private static SqlSessionFactory sqlSessionFactory;
    
        // 加载mybaits核心配置文件,获取SqlSessionFactory对象
        static {
            InputStream is = null;
            try {
                is = Resources.getResourceAsStream("mybatis-config.xml");
                sqlSessionFactory = new SqlSessionFactoryBuilder().build(is);
            } catch (IOException e) {
                e.printStackTrace();
            } finally {
                try {
                    is.close();
                } catch (IOException e) {
                    e.printStackTrace();
                }
            }
        }
    
    
        private MyBatisUtils() {
        }
    
    
        /**
         * 获取SqlSession对象
         *
         * @return SqlSession
         */
        public static SqlSession getSqlSession() {
            return sqlSessionFactory.openSession();
        }
    
        /**
         * 提交事务并释放sqlSession
         *
         * @param sqlSession
         */
        public static void commitAndClose(SqlSession sqlSession) {
            if (sqlSession != null) {
                sqlSession.commit(); //提交事务
                sqlSession.close();
            }
        }
    
        /**
         * 回滚事务并释放sqlSession
         *
         * @param sqlSession
         */
        public static void rollbackAndClose(SqlSession sqlSession) {
            if (sqlSession != null) {
                sqlSession.rollback(); //回滚事务
                sqlSession.close();
            }
        }
    
    }
    
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27
    • 28
    • 29
    • 30
    • 31
    • 32
    • 33
    • 34
    • 35
    • 36
    • 37
    • 38
    • 39
    • 40
    • 41
    • 42
    • 43
    • 44
    • 45
    • 46
    • 47
    • 48
    • 49
    • 50
    • 51
    • 52
    • 53
    • 54
    • 55
    • 56
    • 57
    • 58
    • 59
    • 60
    • 61
    • 62
    • 63
    • 64
    • 65
    • 66
    • 67
    • 68
    • 69
    • 70
    • 71
    • 72
    • 73
    • 74
    • 75
    • 76
    • 77
    • 78



    五、MyBatis实现复杂查询


    1. MyBatis实现模糊查询

    编写接口:

    // 模糊查询
    List<User> getUserLike(String name);
    
    • 1
    • 2

    编写mapper映射文件:

    <!--  模糊查询  -->
    <select id="getUserLike" resultType="user" parameterType="string">
        select * from user where name like #{value}
    </select>
    
    • 1
    • 2
    • 3
    • 4

    方式一:在Java代码执行的时候,传递通配符 % 内容 %

    在这里插入图片描述

    方式二:在SQL拼接中使用通配符。


    2. MyBatis集成Log4j


    参考文章:https://www.cnblogs.com/suhaha/p/11794786.html

    我们使用日志除了要收集一些错误信息,还要查看MyBatis执行SQL语句的执行流程以便于日后排错。

    目前日志框架要么使用Logback,要么使用Log4j2.x,不会使用最早的Log4j了。

    • LOG4J (它要指定一个配置文件)
    • STDOUT_LOGGING (标准日志输出)

    1、导入依赖坐标

    
    <dependency>
        <groupId>log4jgroupId>
        <artifactId>log4jartifactId>
        <version>1.2.17version>
    dependency>
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6

    2、在resources目录下创建一个log4j.properties文件

    #将等级为DEBUG的日志信息输出到console和file这两个目的地,console和file的定义在下面的代码
    log4j.rootLogger=DEBUG,console,file
    
    #控制台输出的相关设置
    log4j.appender.console = org.apache.log4j.ConsoleAppender
    log4j.appender.console.Target = System.out
    log4j.appender.console.Threshold=DEBUG
    log4j.appender.console.layout = org.apache.log4j.PatternLayout
    log4j.appender.console.layout.ConversionPattern=[%c]-%m%n
    
    #文件输出的相关设置
    log4j.appender.file = org.apache.log4j.RollingFileAppender
    log4j.appender.file.File=./log/mybatis.log
    log4j.appender.file.MaxFileSize=10mb
    log4j.appender.file.Threshold=DEBUG
    log4j.appender.file.layout=org.apache.log4j.PatternLayout
    log4j.appender.file.layout.ConversionPattern=[%p][%d{yy-MM-dd}][%c]%m%n
    
    #日志输出级别
    log4j.logger.org.mybatis=DEBUG
    log4j.logger.java.sql=DEBUG
    log4j.logger.java.sql.Statement=DEBUG
    log4j.logger.java.sql.ResultSet=DEBUG
    log4j.logger.java.sql.PreparedStatement=DEBUG
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24

    3、在mybatis核心配置文件上配置日志(在configuration标签的第二个位置)

    在这里插入图片描述


    4、测试:

    在这里插入图片描述

    扩展:配置标准日志输出

    在mybatis-config.xml文件中配置STDOUT_LOGGING为日志的实现。

     <settings>
            <setting name="logImpl" value="STDOUT_LOGGING"/>
     settings>
    
    • 1
    • 2
    • 3

    测试:

    在这里插入图片描述


    3. #{} 和 ${} 的区别 (面试题)


    • #{} 是预编译处理,${}是字符串替换。
    • Mybatis 在处理 #{} 时,会将 sql 中的 #{} 替换为 ? 号,然后调用 PreparedStatement 的 set 方法来赋值;
    • Mybatis 在处理 ${} 时,就是把 ${} 替换成变量的值。
    • 使用 #{} 可以有效的防止 SQL 注入,提高系统安全性 。

    4. Limit实现分页


    分页有很多种实现方式:如Limit实现分页、RowBounds 分页、分页插件(PageHelper)等

    4.1 Limit实现分页


    不带条件查询的分页

    编写接口:

    /**
     * 分页查询用户列表(没有条件)
     * 使用Map传参(如 startIndex、pageSize)
     *
     * @param map
     * @return
     */
    List<User> getUserByLimit(Map<String, Integer> map);
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8

    编写mapper映射文件:

    
    <select id="getUserByLimit" resultType="user" parameterType="map">
        select *
        from user
        limit #{startIndex},#{pageSize}
    select>
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6

    测试:

    @Test
    public void testSelectUserByLimit() {
        Map<String, Integer> map = new HashMap<>();
        Integer pageNo = 2;   //码页
        Integer pageSize = 3; //每页显示3条数据
        Integer startIndex = (pageNo - 1) * pageSize; //分页查询的起始位置
        map.put("startIndex",startIndex);
        map.put("pageSize",pageSize);
    
        SqlSession sqlSession = MyBatisUtils.getSqlSession();
        UserMapper mapper = sqlSession.getMapper(UserMapper.class);
        List<User> userList = mapper.getUserByLimit(map);
        userList.forEach(System.out::println);
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14

    在这里插入图片描述



    六、MyBatis参数详解


    MyBatis的参数指的就是Mapper接口中函数的参数,该Mapepr接口中函数的参数类型可以分为如下四种:

    • 简单类型,例如Stirng、Long、int等等

    • POJO或者Map,例如 Student、HashMap

    • 多个参数,例如 userName、passWord,(注解、map)(不推荐使用)

    • POJO包装类对象,例如 QueryVO ,T表示泛型类型,为了更加通用而设计,适应场景就是复杂查询。


    1. 为函数传递简单类型参数


    如果方法中只有一个参数,然后以简单类型传参,那么在映射文件中parameterType的值就是简单类型的别名,在SQL语句中用 #{任意字符串} 引入简单类型的参数 。

    // 根据ID查询用户
    User findUserById(int id);
    
    • 1
    • 2
    <select id="findUserById" resultType="user" parameterType="int">
        select *
        from user
        where id = #{id}
    select>
    
    • 1
    • 2
    • 3
    • 4
    • 5

    MyBatis常用的类型别名如下:

    在这里插入图片描述


    2. 为函数传递多个参数


    使用注解@Param 传递多个参数

    // 用户登录
    User login(@Param("name") String userName, @Param("pwd") String passWord);
    
    • 1
    • 2
    <select id="login" resultType="user" >
        select * from user where name=#{name} and pwd=#{pwd}
    select>
    
    • 1
    • 2
    • 3
    @Test
    public void testLogin() {
        SqlSession sqlSession = MyBatisUtils.getSqlSession();
        UserMapper mapper = sqlSession.getMapper(UserMapper.class);
        String userName = "张三";
        String passWord = "123456";
        User user = mapper.login(userName, passWord);
        System.out.println(user!=null?"登录成功":"登录失败");
        sqlSession.close();
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10

    如果传递多个参数,在映射文件中直接调用参数名会出错误的,他会让你以param1,…,paramn或者 arg1…argn方式调用参数。

    在这里插入图片描述

    MyBatis为开发者提供了一个注解@Param,使用它可以为参数起名字,在映射配置文件中不需要定义parameterType属性,MyBatis它自动获取,从而提高代码的可读性,但是这会带来一个麻烦。如果SQL很复杂拥有的参数大于10个,则需要为接口处理多个参数名,那么使用起来就很不容易了,不过不必担心,MyBatis还提供传递JavaBean的形式。


    3. 为函数传递POJO或者Map


    通常使用POJO(实体类)对象或者Map来封装多个参数,前者需要定义模板,后者不用插入指定的参数比较灵活。

    方案一:将多个参数封装到pojo中,那么映射配置文件中parameterType的值就是POJO的全限定名(即 包名+类名)或者是别名,在SQL语句中使用 #{POJO属性名} 来引入参数。

    // 添加用户
    int addUser(User user);
    // 修改用户
    int updateUser(User user);
    
    • 1
    • 2
    • 3
    • 4
    
    <insert id="addUser" parameterType="user">
        insert into user(name, pwd, gender, addr) value (#{name}, #{pwd}, #{gender}, #{addr})
    insert>
    
    
    <update id="updateUser" parameterType="user">
        update user
        set name=#{name},
        pwd=#{pwd}
        where id = #{id}
    update>
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12

    方案二:将多个参数封装到一个Map集合中(前提条件是这些参数没有对应的POJO),然后映射配置文件中parameterType的值设置为map,最后在SQL语句中使用 #{map的key} 来引入参数。

    // 带条件的分页查询
    List<User> getUserByPage(Map<String, Integer> map);
    
    • 1
    • 2
    <select id="getUserByPage" resultType="user" parameterType="map">
        select *
        from user
        <where>
            <if test="pwd!=null">
                and pwd = #{pwd}
            if>
        where>
        limit #{startIndex},#{pageSize}
    select>
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    @Test
    public void testSelectUserByPage() {
        Map<String, Integer> map = new HashMap<>();
        Integer pageNo = 1;   //码页
        Integer pageSize = 3; //每页显示3条数据
        Integer startIndex = (pageNo - 1) * pageSize; //分页查询的起始位置
        map.put("startIndex",startIndex);
        map.put("pageSize",pageSize);
        map.put("pwd",123456); //筛选密码为123456的用户
    
        SqlSession sqlSession = MyBatisUtils.getSqlSession();
        UserMapper mapper = sqlSession.getMapper(UserMapper.class);
        List<User> userList = mapper.getUserByPage(map);
        userList.forEach(System.out::println);
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15

    Map几乎适用所有场景,但是我们用得不多。原因有两个:首先,Map是一个键值对集合,使用者要通过阅读它的键,才能明白其作用;其次,使用Map不能限定其传递的数据类型,因此业务性质不强,可读性差,使用者要读懂代码才能知道需要传递什么参数给它,所以不推荐用这种方式传递多个参数。



    4. 为函数传递POJO包装类对象


    POJO包装类对象,也就是在一个对象中嵌入了另一个对象和其他条件。(套娃操作)

    需求:使用分页查询,查询性别为男的用户列表

    1、封装POJO包装类

    package com.baidou.vo;
    
    import com.baidou.pojo.User;
    
    /**
     * 用户查询条件
     *
     * @author 白豆五
     * @version 2022/12/1 23:02
     * @since JDK8
     */
    public class QueryVO {
        //页码(当前页)
        private Long pageNo;
        // 每页显示的条数
        private Long pageSize;
        //偏移量
        private Long offSet;
        // 查询用户的条件
        private User userCondition;
    
        public Long getOffSet() {
            return (pageNo - 1) * pageSize; //分页查询的起始位置
        }
    
        public Long getPageNo() {
            return pageNo;
        }
    
        public void setPageNo(Long pageNo) {
            this.pageNo = pageNo;
        }
    
        public Long getPageSize() {
            return pageSize;
        }
    
        public void setPageSize(Long pageSize) {
            this.pageSize = pageSize;
        }
    
        public User getUserCondition() {
            return userCondition;
        }
    
        public void setUserCondition(User userCondition) {
            this.userCondition = userCondition;
        }
    
        /*解决问题:
        org.apache.ibatis.exceptions.PersistenceException:
    
        ### Error querying database.  Cause: org.apache.ibatis.reflection.ReflectionException: There is no getter for property named 'gender' in 'class com.baidou.vo.QueryVO'
    
        ### Cause: org.apache.ibatis.reflection.ReflectionException: There is no getter for property named 'gender' in 'class com.baidou.vo.QueryVO'
        */
        public char getGender() {
            return userCondition.getGender();
        }
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27
    • 28
    • 29
    • 30
    • 31
    • 32
    • 33
    • 34
    • 35
    • 36
    • 37
    • 38
    • 39
    • 40
    • 41
    • 42
    • 43
    • 44
    • 45
    • 46
    • 47
    • 48
    • 49
    • 50
    • 51
    • 52
    • 53
    • 54
    • 55
    • 56
    • 57
    • 58
    • 59
    • 60

    2、定义UserMapper接口

    // 分页查询用户列表(有条件)
    List<User> getUserByQueryVO(QueryVO queryVO);
    
    • 1
    • 2

    3、编写映射

    <select id="getUserByQueryVO" resultType="user" parameterType="com.baidou.vo.QueryVO">
        select *
        from user
        <where>
            <if test="gender!=null">
                and gender=#{userCondition.gender}
            if>
        where>
        limit #{offSet},#{pageSize}
    select>
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10

    4、测试

    @Test
    public void testGetUserByQueryVO() {
        QueryVO queryVO = new QueryVO();
        User userCondition = new User();
        userCondition.setGender('男');
        queryVO.setUserCondition(userCondition);
        queryVO.setPageNo(1L); //设置当前页面
        queryVO.setPageSize(3L); //每页显示3条数据
    
        SqlSession sqlSession = MyBatisUtils.getSqlSession();
        UserMapper mapper = sqlSession.getMapper(UserMapper.class);
        List<User> userVoList = mapper.getUserByQueryVO(queryVO);
        userVoList.forEach(System.out::println);
        sqlSession.close();
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15

    在这里插入图片描述



    七、MyBatis结果集详解


    我们学习MyBatis框架主要学习MyBatis的核心配置文件MyBatis映射配置文件

    MyBatis参数、MyBatis结果集、MyBatis动态SQL这三节都是围绕MyBatis映射配置文件的。

    MyBatis结果集就是MyBatis 执行查询的SQL语句时返回的结果集,该结果集有三种类型:

    • 单行单列的值

    • 单行多列的值(用对象封装)

    • 多行多列的值 (用List集合封装)

    需要在映射配置文件中配置这三种结果;也就是