SpringBoot整合MyBatisPlus框架

1. 简介

这里我们将MyBatisPlus(以下简称mp)框架整合到SpringBoot项目中, mp框架相对于基础版mybatis通用版mybatis 有如下几个优点:

  • xml文件零配置: 对于单表查询几乎实现零xml文件配置.
  • 丰富的查询条件: 对于多条件查询利用Wrapper接口可以实现和Hibernate相媲美的查询.
  • 自带分页功能: 通过将PaginationInterceptor类注入到Spring容器中就可以实现分页查询.

其实还有很多优点我这里就不一一列举了, 此片文章只讨论 单表查询 以及 单数据源配置 , 且没有利用到 mp框架的自动生成代码功能 , 要想详细的了解请访问如下网址:

2. 版本

  • SpringBoot: 2.1.4.RELEASE.
  • mybatis 2.0.1
  • mybatis-plus: 3.1.0

3 . 代码实现

  1. 创建SpringBoot项目引入Web, mybatis, mysql, lombok插件.

  2. 外部网站搜索引入mybatis-plus-boot-starter maven依赖.

    <!-- 集成 Mybatis-plus 插件-->
    <dependency>
      <groupId>com.baomidou</groupId>
      <artifactId>mybatis-plus-boot-starter</artifactId>
      <version>3.1.0</version>
    </dependency>
    
  3. 创建实体类, 我们这里以Book类为例子, 其中数据库信息如下:

    create table test.t_book
    (
        book_id     bigint(11) auto_increment comment '主键'
            primary key,
        book_name   varchar(24)    not null comment '书名',
        book_author varchar(24)    not null comment '作者',
        book_price  decimal(10, 2) not null comment '价格',
        push_date   datetime       not null comment '发布时间'
    )
        comment '书籍商品信息';
    

    实体类Book信息如下:

    package com.pyi.config.mybatisplus.model;
    
    import com.baomidou.mybatisplus.annotation.TableId;
    import com.baomidou.mybatisplus.annotation.TableName;
    import lombok.Data;
    
    import java.math.BigDecimal;
    import java.util.Date;
    
    /**
     * @author pyi
     * @date 2019-04-09
     */
    // @Data 注解来源于 `lombok` 插件, 实际上的作用是帮助自动生成`Get/Set/ToString/Equal方法`
    // 具体信息我们可以访问 https://projectlombok.org/features/all 了解.
    @Data
    // @TableName 当数据库名称和类名不一致的时候通过 value 属性指定映射关系
    @TableName
    public class Book {
    
        /**
         * 这里要是没有作全局主键类型配置, 那么就需要 借用 `@TableId` 的属性 type 指明填充主键的方式, 填充参考 IdType.class
         */
        @TableId
        private Integer bookId;
        private String bookName;
        private String bookAuthor;
        private BigDecimal bookPrice;
        private Date pushDate;
    }
    

    这里我们值得注意的是:

    • @Data 注解来源于lombok插件. 需要了解的朋友可以访问 lombok

    • Bookt_book不一致为什么没有借助@TableName注解修改映射名称? 这个我们后面会有说到.

    • @TableId 没有指定主键 的填充方式, 那么默认的填充方式是什么?

      带着上面的问题我们`接下来作下面的事情.

  4. 创建mappper 包专门用来存放mapper接口. 并且创建BaseMapper接口继承mp 的BaseMapper 接口.

    package com.pyi.config.mybatisplus.mapper;
    
    /**
     * @author pyi
     * @date 2019-04-09
     */
    public interface BaseMapper<T> extends com.baomidou.mybatisplus.core.mapper.BaseMapper<T> {
    }
    
    

    然后就创建我们的业务mappe接口 继承我们自己创建的基类BaseMapper接口即可.

    package com.pyi.config.mybatisplus.mapper;
    
    import com.pyi.config.mybatisplus.model.Book;
    
    /**
     * @author pyi
     * @date 2019-04-09
     */
    public interface BookMapper extends BaseMapper<Book> {
    
    }
    

    注意要是我们没有使用全局@MapperScan注解指向我们的mapper包的话, 我们就要为每个业务mapper使用@Mapper业务mapper注入到Spring容器中.

  5. resource下创建mapper文件夹专门用来存放mapper.xml映射配置文件. 这里我们可以在下面创建我们的业务mapper.xml文件. 这里我们创建一个空的BookMapper.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">
    <!--这里 namespace 指向业务mapper的接口-->
    <mapper namespace="com.pyi.config.mybatisplus.mapper.BookMapper">
    </mapper>
    
  6. SpringBoot启动类同级或者是子级下面创建MyBatisPlusConfig.class类, 方便利用SpringBoot启动类中@ComponentScan 注解结合MyBatisPlusConfig.class@Configuration注解, 实现将 MyBatisPlusConfig.class作为配置类注入到Spring容器中.

    package com.pyi.config.mybatisplus.config;
    
    import com.baomidou.mybatisplus.extension.plugins.PaginationInterceptor;
    import com.pyi.config.mybatisplus.mapper.BaseMapper;
    import org.mybatis.spring.annotation.MapperScan;
    import org.springframework.context.annotation.Bean;
    import org.springframework.context.annotation.Configuration;
    
    /**
     * MybatisPlus配置类
     * @author pyi
     * @date 2019-04-10
     */
    @Configuration
    // @MapperScan 注解指示mapper接口的位置, 注意使用 markerInterface属性将基础映射类过滤掉不参与Spring扫描
    @MapperScan(basePackages = "com.pyi.config.mybatisplus.mapper", markerInterface = BaseMapper.class)
    public class MybatisPlusConfig {
    
      // 要想在查询中使用分页Page功能, 那么必须配置 PaginationInterceptor, 将其注入到Spring容器中.
        @Bean
        public PaginationInterceptor paginationInterceptor() {
            PaginationInterceptor paginationInterceptor = new PaginationInterceptor();
            return paginationInterceptor.setDialectType("mysql");
        }
    }
    
  7. 配置SpringBoot的配置文件application.context.

    # 配置数据源信息
    spring.datasource.driver-class-name=com.mysql.cj.jdbc.Driver
    spring.datasource.username=root
    spring.datasource.password=Yi844579582!@#
    spring.datasource.url=jdbc:mysql://localhost:3306/test?useSSL=true
    
    # 配置MyBatis-Plus(具体各参数含义可参照 MyBatisPlusProperties.class 的各个属性))
    mybatis-plus.mapper-locations=classpath*:/mapper/*.xml
    # 配置MyBatis-Plus表映射的相关属性(这里是全局配置, 要是没有配置的话, 我们必须在对象里面单独配置 具体含义请参照 DbConfig,class 类)
    mybatis-plus.global-config.db-config.db-type=mysql
    mybatis-plus.global-config.db-config.id-type=auto
    mybatis-plus.global-config.db-config.table-prefix=t_
    mybatis-plus.global-config.db-config.table-underline=true
    
    # 添加日志处理(这里我们是为了在测试类中打印mybatis执行的sql语句)
    logging.level.com.pyi.config.mybatisplus = debug
    

    这里我们就第二步中创建的实体类的几个遗留问题简单说下:

    • Bookt_book不一致为什么没有借助@TableName注解修改映射名称? 因为我们在全局配置中使用了mybatis-plus.global-config.db-config.table-prefix=t_配置, 这里就说明将所有的类都会添加t_开头用来与数据库表名映射.
    • @TableId 没有指定主键 的填充方式, 那么默认的填充方式是什么? 这里我们用到了mybatis-plus.global-config.db-config.id-type=auto 属性指定默认的填充方式是auto自动增长, 要是不指定的话, 默认采用的是id_worker属性. 具体各个参数的含义我们可以访问 IdType 类进行查询.
    • 一般可以嵌入到SpringBoot的项目都会有一个配置类, 比如mp框架是MyBatisPlusProperties类, 里面的属性就是可以在SpringBoot全局配置中进行配置的. 要想了解各个参数的含义, 大家可以访问 MyBatisPlusProperties进行查看. 这里要说的是, 这个方法可以扩展到其他的SpringBoot项目. 大家遇到不懂的配置的时候就可以到相应的类中进行查看注释, 了解其原理是干嘛用的.
  8. 注: 一般baseMapper已经有大部分的接口供我们调用, 一般配置到第七步我们就结束了. 但是如果项目中涉及到批量插入等批量操作的时候, 那么我们就还需要进行最后一步创建Service层.

    这里我们创建BookService接口和BookServiceImpl实现类, 并将BookServiceImpl继承mp框架的ServiceImpl类.

    package com.pyi.config.mybatisplus.service.impl;
    
    import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
    import com.pyi.config.mybatisplus.mapper.BookMapper;
    import com.pyi.config.mybatisplus.model.Book;
    import com.pyi.config.mybatisplus.service.BookService;
    import org.springframework.stereotype.Service;
    
    /**
     * @author pyi
     * @date 2019-04-10
     */
    @Service
    public class BookServiceImpl extends ServiceImpl<BookMapper, Book> implements BookService{
    }
    

    注意Service层我们要引入Service注解, 目的是为了将其注入到Spring容器中.

    这里的ServiceImpl类对BaseMapper的方法都做了封装, 且还包含有一些批量的操作, 比如saveBatch()方法等,具体涉及到哪些方法, 大家可以去这个类中查看.

4. 测试

这里我们编写了几个增删改查的典型方法供大家参考.

package com.pyi.config.mybatisplus;

import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.baomidou.mybatisplus.core.conditions.update.UpdateWrapper;
import com.baomidou.mybatisplus.core.metadata.IPage;
import com.baomidou.mybatisplus.core.toolkit.Wrappers;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.pyi.config.mybatisplus.model.Book;
import com.pyi.config.mybatisplus.service.impl.BookServiceImpl;
import lombok.extern.slf4j.Slf4j;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.test.context.SpringBootTest;
import org.springframework.test.context.junit4.SpringRunner;

import java.math.BigDecimal;
import java.util.*;

@RunWith(SpringRunner.class)
@SpringBootTest
@Slf4j
public class MybatisplusApplicationTests {


    @Autowired
    private BookServiceImpl bookService;

    /**
     * 单次插入
     */
    @Test
    public void save() {
        Book book = new Book();
        book.setBookName("MyBatis-Plus");
        book.setBookAuthor("pyi");
        book.setBookPrice(BigDecimal.valueOf(33.33));
        book.setPushDate(new Date());
        // 单插入
        boolean save = bookService.save(book);
        System.out.println(save);
    }

    /**
     * 批量插入
     */
    @Test
    public void saveBatch() {
        List<Book> bookList = new ArrayList<>();
        for (int i = 0; i < 10; i++) {
            Book book = new Book();
            book.setBookName("MyBatis-Plus" + i);
            book.setBookAuthor("pyi");
            book.setBookPrice(BigDecimal.valueOf(33.33));
            book.setPushDate(new Date());
            bookList.add(book);
        }
        // 这里saveBatch建立了事务, 一旦出现异常会自动回滚
        boolean b = bookService.saveBatch(bookList);
        System.out.println(b);
    }

    /**
     * 删除我们将两种特殊方式
     * 1. 按列删除 removeByMap()
     * 2. 按条件删除 remove(Wrap)
     */
    @Test
    public void delete() {

        // DELETE
        //  FROM t_book
        //  WHERE book_id = 10;
        Map<String, Object> columnMap = new HashMap<>();
        // 注意这里的 key => 用的是数据库的字段
        columnMap.put("book_id", 10);
        boolean removeByMap = bookService.removeByMap(columnMap);
        System.out.println(removeByMap);

        // DELETE
        // FROM t_book
        // WHERE book_author = 'pyi' AND book_price BETWEEN '30' AND '40' AND push_date >= '2019-04-10 04:03:21';
        QueryWrapper<Book> queryWrapper = new QueryWrapper<>();
        queryWrapper.eq("book_author", "pyi")
                .between("book_price", "30", "40")
                .ge("push_date", "2019-04-10 04:03:21");
        System.out.println(bookService.remove(queryWrapper));
    }

    /**
     * 修改我们只讨论条件修改的方式
     */
    @Test
    public void update() {
        // UPDATE t_book SET book_name = concat(book_name, '_1'),book_price=44.44
        // WHERE book_author = 'pyi' AND book_id > 2;
        UpdateWrapper<Book> updateWrapper = new UpdateWrapper<>();
        Map<String, Object> updateMap = new HashMap<>();
        updateMap.put("book_author", "pyi");
        updateWrapper.setSql("book_name = concat(book_name, '_1')")
                .set("book_price", 44.44)
                .allEq(updateMap)
                .gt("book_id", 2);
        System.out.println(bookService.update(updateWrapper));
    }

    @Test
    public void select() {

        // 根据主键查询
        System.out.println(bookService.getById(1));

        // 根据条件查询并获取部分字段 (注意 getMap只会返回一个Map 对象, 要是条件满足多个则会返回第一个)
        QueryWrapper<Book> queryWrapper = new QueryWrapper<>();
        queryWrapper.select("book_id", "book_name")
                .ge("book_id", 1)
                .last(" limit 1");
        System.out.println(bookService.getMap(queryWrapper));

        // getOne 返回一个对象, 要是有多个对象返回第一个, 注意要是 第二个参数true(默认) 那么返回多个对象就会抛出异常
        System.out.println(bookService.getOne(queryWrapper, false));

        // list 返回多个对象集合
        bookService.list(new QueryWrapper<Book>().gt("book_id",1)).forEach(System.out::println);
    }

    /**
     * 注意, 要使用分页必配置 PaginationInterceptor到Spring容器中
     */
    @Test
    public void pagination() {

        // SELECT COUNT(1) FROM t_book;
        // SELECT book_id,book_name,book_author,book_price,push_date FROM t_bookLIMIT 1,1;

        Page<Book> bookPage = new Page<>(2, 1);
        IPage<Book> bookIPage = bookService.page(bookPage, Wrappers.emptyWrapper());
        bookIPage.getRecords().forEach(System.out::println);
    }
}

5. 项目地址

SpringBoot整合MyBatisPlus

猜你喜欢

转载自blog.csdn.net/qq844579582/article/details/89211577