• 快速掌握 MyBatis 框架(二)


    文章目录

    一、前言

    快速掌握 MyBatis 框架(一)

    1.1 数据库与表

    create database if not exists library;
    use library;
    
    drop table if exists book;
    create table book(
        id int primary key auto_increment,  -- 书籍Id
        bookName varchar(100) not null,     -- 书名
        content varchar(1024) not null,     -- 书籍内容
        authorId int not null,              -- 作者Id
        `state` int default 1               -- 借出状态,默认为1,未借出
    );
    drop table if exists author;
    create table author(
        id int primary key auto_increment,  -- 作者Id
        authorName varchar(100) not null,   -- 作者名字
        age int,                            -- 作者年龄
        nationality varchar(250)            -- 作者国籍
    );
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18

    1.2 实体类

    //书籍类
    @Data
    public class Book {
        private Integer id;
        private String bookName;
        private String content;
        private Integer authorId;
        private Integer state;
        private Author author;
    }
    
    
    //作者类
    @Data
    public class Author {
        private Integer id;
        private String authorName;
        private Integer age;
        private String nationality;
        private List books;
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21

    1.3 MyBatisX 插件

    在写 MyBatis 代码的时候有一个非常好用的插件——MyBatisX

    选择 File->Settings ,然后进行如下操作进行插件的安装

    在这里插入图片描述

    该插件可以实现接口代码和对应的 XML 文件中的代码的跳转

    在这里插入图片描述

    而且写好一个 接口方法后可以在对应的 XML 文件中自动生成代码(出现红下划线,Alt+Enter,选择第一个选项),当然,这样的方式生成的标签不一定是我们想要的

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

    1.4 SQL 日志查看配置

    为了查看写好的 SQL ,可以在配置文件中进行配置,如此,在控制台就可以查看 SQL 日志

    mybatis:
      configuration:
        log-impl: org.apache.ibatis.logging.stdout.StdOutImpl
    
    • 1
    • 2
    • 3

    二、多表查询

    在前面一篇文章中有讲数据库的增加(insert)、删除(delete)、修改(update)、查询(select)操作

    增删改这三个操作返回的值都是影响的行数,所以在写 SQL 的 XML 时并不需要指定返回类型,但是如果是查询操作就需要通过 resultType 来设置返回类型,就算是 String 类型,返回值也要设置为 resultType =“java.lang.String”

    但是如果进行多表查询,实体类中就会有一个属性为另一个实体类,比如上面的实体类定义中,一本书对应一个作者,想要将作者的完整信息都放在书籍类中。一个作者可以写很多本书,想要将这个作者写的所有书的信息都放在一个 List 中。这样的情况,简简单单通过 resultType 已经没有办法实现,如果只是使用 resultType ,会发现对应的类的属性值为 null(变量 author 和 变量 books 的值为 null)

    此时就需要使用 resultMap ,返回一个字典映射

    2.1 一对一

    一本书对应一个作者的情况

    interface

    @Mapper
    public interface BookMapper {
        public Book getBookById(Integer id);
    }
    
    • 1
    • 2
    • 3
    • 4

    XML

    BookMapper.xml

    
    
    
    
        
            
            
            
            
            
            
            
        
        
    
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22

    解释:

    1. select 标签中的 resultMap 的值 “BaseMap” 就是一个标识和上面 resultMap 标签中的 id 属性值 “BaseMap” 是对应的,起什么名字都行,
    2. resultMap 标签中的 type 属性值为映射的实体类的包名加类名
    3. id 标签指的是主键result 标签指的是普通列
    4. property 属性指的是程序中的属性名,column 属性指的是数据库中的字段名。因此,即使程序中的属性名和数据库中的字段名不一致也不要紧,通过这样的映射就不会出错
    5. 由于是一对一的多表查询,使用的是association标签。
      • property属性指的是 Book 类中关联的 Author 类的变量,即 author;
      • resultMap 属性指的是指定关联的结果集映射,将基于该映射配置来组织用户数据,这里关联的就是 AuthorMapper 里的 BaseMap(就是下面的代码);
      • columnPrefix 属性指的是给关联的数据库中的 column 添加一个前缀(如果不添加前缀,当 author 表和 book 表中同时有 id 字段,查询结果时一定会产生覆盖,使得两个 id 的值一样);

    AuthorMapper.xml

    
    
    
        
            
            
            
            
        
    
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11

    单元测试代码

    @SpringBootTest
    class BookMapperTest {
        @Autowired
        private BookMapper mapper;
        @Test
        void getBookById() {
            System.out.println(mapper.getBookById(1));
        }
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9

    结果显示

    在这里插入图片描述

    2.2 一对多

    一对多和一对一的写法大体上是一样的额,不同的是一对一使用的是 association 标签,一对多使用的是 collection 标签

    interface

    public List getAuthor(Integer id);
    
    • 1

    XML

    
    
    
        
            
            
            
            
            
            
        
        
     
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20

    关联的BookMapper 中的 BaseMap 在上面一对一的代码中已经写了

    单元测试代码

    @Test
    void getAuthor() {
        List list = mapper.getAuthor(1);
        list.stream().forEach(n-> System.out.println(n));
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5

    结果展示

    在这里插入图片描述

    三、动态 SQL 使用

    为了应对各种各样的需求,就需要动态 SQL 完成不同条件下不同的 SQL 拼接

    3.1 < if > 标签

    在完善信息的时候,有些信息是必须要填的,有些是非必填的。就像 author 表中作者的信息一样,只有 authorName 是一定要填写的,age 和 nationality 是非必填的,那么在插入数据的时候,就需要应对各种信息插入情况,就需要用 < if > 标签来判断传来的值是否为 null,如果是就不将内容拼接到 SQL 中

    interface

    public int setAuthor3(Author author);
    
    • 1

    XML

    
        insert into author(authorName
        
            ,age
        
        
            ,nationality
        
        ) values(#{authorName}
        
            ,#{age}
        
        
            ,#{nationality}
        
        )
    
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17

    解释:

    1. 通过 if 标签中的 test属性中的内容(对象中的属性)是否为空来决定是否将其拼接到 SQL 语句中
    2. 需要注意拼接时的逗号以及括号,保证在任何情况下都能组装成正确的 SQL 语句
    3. 由于需要判空,因此创建实体类的时候最好使用包装类,比如使用 Integer 类型而不是 int 类型。因为 int 类型默认值为 0 ,不会为 null,而 0 和 null 还是有很大区别的,使用 int 类型会存在报错的风险

    测试代码展示

    @Test
    void setAuthor3() {
        Author author = new Author();
        author.setAuthorName("钱七");
        author.setNationality("马来西亚");
        System.out.println("更新的数据条数:"+mapper.setAuthor3(author));
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7

    结果显示

    在这里插入图片描述

    3.2 < trim > 标签

    该标签是配合 if 标签进行使用,试想极端情况,所有的参数都是非必传的,那么在不知道哪个参数是第一个,哪个参数是最后一个的情况下,一定会有多出来的逗号,trim 标签就可以解决这样的问题

    trim 标签的属性

    • prefix:表示整个语句块以 prefix 的值作为前缀
    • suffix:表示整个语句块以 suffix 的值作为后缀
    • prefixOverrides:表示整个语句块要去除的前缀
    • suffixOverrides:表示整个语句块要去除的后缀

    interface

    public int setAuthor4(Author author);
    
    • 1

    XML

    
        insert into author
        
            
                ,authorName
            
            
                ,age
            
            
                ,nationality
            
        
        values
        
            
                #{authorName},
            
            
                #{age},
            
            
                #{nationality},
            
        
    
    
    • 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

    注意:如果 trim 标签中的内容没有一条条件成立 ,就不会执行 trim 语句的内容了,包括其属性也不会生效。因此如果有必传参数,就往 trim 标签中添加必传参数;如果没有任何必传参数,前缀后缀相关属性就在 trim 中设置

    单元测试代码

    @Test
    void setAuthor4() {
        Author author = new Author();
        author.setAuthorName("朱八");
        author.setAge(66);
        System.out.println("更新的数据条数:"+mapper.setAuthor4(author));
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7

    结果显示

    在这里插入图片描述

    3.3 < where > 标签

    传入一个对象,根据属性进行 where 条件查询,只要对象中的属性不为 null 就是查询条件

    interface

    public List getBookByIdOrAuthorId(Book book);
    
    • 1

    XML

    
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11

    解释:

    1. where 标签自带 where 关键字,并且会自动去除多余的 and
    2. 可以使用 < trim prefix=“where” prefixOverrides=“and” > 替换

    单元测试代码

    @Test
    void getBookByIdOrAuthorId() {
        Book book = new Book();
        book.setAuthorId(1);
        List list = mapper.getBookByIdOrAuthorId(book);
        list.stream().forEach(n-> System.out.println(n));
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7

    结果显示

    在这里插入图片描述

    3.4 < set > 标签

    传入一个对象,根据属性进行更新用户的数据,比如根据传入的对象的 id ,修改其他不为 null 的属性

    interface

    public int updateBook(Book book);
    
    • 1

    XML

    
        update book 
        
            
                bookName=#{bookName},
            
            
                content=#{content},
            
            
                authorId=#{authorId}
            
        
        where id=#{id}
    
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15

    解释:

    1. set 标签自带 set 关键字,会自动去除多余的逗号
    2. 可以使用 < trim prefix=“set” suffixOverrides=“,”> 替换

    单元测试代码

    @Test
    void updateBook() {
        Book book = new Book();
        book.setId(1);
        book.setContent("更新内容~");
        System.out.println("更新数据的条数:"+mapper.updateBook(book));
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7

    结果显示

    在这里插入图片描述

    3.5 < foreach > 标签

    需要对一个集合遍历时使用该标签

    foreach 标签属性

    • collection:绑定方法参数中的集合(List、Set、Map、数组…)
    • item:用于指定遍历时的每一个对象
    • open:整个语句块开头的字符串
    • close:整个语句块结束的字符串
    • separator:遍历元素之间间隔的字符串

    interface

    public int deleteByIdList(List list);
    
    • 1

    XML

    
        delete from book where id in
        
            #{bookId}
        
    
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6

    单元测试代码

    @Test
    void deleteByIdList() {
        List list = new ArrayList<>();
        list.add(1);
        list.add(3);
        System.out.println("更新数据的条数:"+mapper.deleteByIdList(list));
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7

    结果显示

    在这里插入图片描述

    完~~~

    先自我介绍一下,小编13年上师交大毕业,曾经在小公司待过,去过华为OPPO等大厂,18年进入阿里,直到现在。深知大多数初中级java工程师,想要升技能,往往是需要自己摸索成长或是报班学习,但对于培训机构动则近万元的学费,着实压力不小。自己不成体系的自学效率很低又漫长,而且容易碰到天花板技术停止不前。因此我收集了一份《java开发全套学习资料》送给大家,初衷也很简单,就是希望帮助到想自学又不知道该从何学起的朋友,同时减轻大家的负担。添加下方名片,即可获取全套学习资料哦

  • 相关阅读:
    langchain:Prompt在手,天下我有
    基于Hardhat和Openzeppelin开发可升级合约(二)
    小红书怎么上精选笔记?小红书精选笔记要怎么弄
    file文件操作—操作系统底层关系_写入文件
    数据库上云实践:使用Ora2pg进行数据库迁移
    Pytest框架中fixture功能详解
    Mit6.006-lecture04-Hashing
    手摸手带你 在Windows系统中安装Istio
    网页转长图插件html2canvas【前端】
    基于深度学习的中文情感分析系统python flask
  • 原文地址:https://blog.csdn.net/m0_67400973/article/details/126081238