Springboot 系列(十二)使用 Mybatis 集成 pagehelper 分頁插件和 mapper 插件

前言

在 Springboot 系列文章第十一篇裏(使用 Mybatis(自動生成插件) 訪問數據庫),實驗了 Springboot 結合 Mybatis 以及 Mybatis-generator 生成插件的開發過程,其實對於 Mybatis 來說還有不少優秀方便好用的插件,好比此次要演示的 通用 Mapper 生成插件和分頁插件。html

<!-- more -->java

數據庫準備

既然是持久層框架,先準備一個用於實驗操做的數據表,此次仍是使用上一個實驗使用的 mysql 數據庫中的 springboot.book 數據表。mysql

未建立的能夠在 mysql 數據庫的 springboot 庫中建立表 book 用於演示。git

CREATE TABLE `book` (
  `id` int(11) NOT NULL AUTO_INCREMENT,
  `author` varchar(255) DEFAULT NULL COMMENT '書籍做者',
  `name` varchar(255) DEFAULT NULL COMMENT '書籍名稱',
  `price` float NOT NULL COMMENT '書籍價格',
  `create_time` datetime NOT NULL COMMENT '建立時間',
  `description` varchar(255) DEFAULT NULL COMMENT '書籍描述',
  PRIMARY KEY (`id`)
) ENGINE=InnoDB AUTO_INCREMENT=15 DEFAULT CHARSET=utf8;

增長測試數據。github

INSERT INTO `springboot`.`book`(`id`, `author`, `name`, `price`, `create_time`, `description`) VALUES (2, '金庸', '笑傲江湖', 12, '2018-09-01 10:10:12', '是做家金庸創做的一部長篇武俠小說');
INSERT INTO `springboot`.`book`(`id`, `author`, `name`, `price`, `create_time`, `description`) VALUES (3, '羅貫中', '三國演義', 22, '2018-09-01 10:10:16', '是做家羅貫中創做的一部長篇歷史小說');
INSERT INTO `springboot`.`book`(`id`, `author`, `name`, `price`, `create_time`, `description`) VALUES (4, '吳承恩', '西遊記', 17, '2018-09-01 10:10:19', '是做家吳承恩創做的一部長篇小說');
INSERT INTO `springboot`.`book`(`id`, `author`, `name`, `price`, `create_time`, `description`) VALUES (5, '金庸1535767819284', '笑傲江湖1535767819284', 43, '2018-09-01 10:10:19', '是做家金庸創做的一部長篇武俠小說1535767819284');
INSERT INTO `springboot`.`book`(`id`, `author`, `name`, `price`, `create_time`, `description`) VALUES (6, '金庸1535767819679', '笑傲江湖1535767819679', 24, '2018-09-01 10:10:20', '是做家金庸創做的一部長篇武俠小說1535767819679');
INSERT INTO `springboot`.`book`(`id`, `author`, `name`, `price`, `create_time`, `description`) VALUES (7, '羅貫中1535769035138', '三國演義1535769035138', 20, '2018-09-01 10:30:35', '是羅貫中創做的一部小說1535769035138');
INSERT INTO `springboot`.`book`(`id`, `author`, `name`, `price`, `create_time`, `description`) VALUES (9, '金庸1535783613226', '笑傲江湖1535783613226', 30, '2018-09-01 14:33:33', '是做家金庸創做的一部長篇武俠小說1535783613226');
INSERT INTO `springboot`.`book`(`id`, `author`, `name`, `price`, `create_time`, `description`) VALUES (10, '金庸1535783618455', '笑傲江湖1535783618455', 30, '2018-09-01 14:33:38', '是做家金庸創做的一部長篇武俠小說1535783618455');
INSERT INTO `springboot`.`book`(`id`, `author`, `name`, `price`, `create_time`, `description`) VALUES (11, '金庸1535783620634', '笑傲江湖1535783620634', 30, '2018-09-01 14:33:41', '是做家金庸創做的一部長篇武俠小說1535783620634');
INSERT INTO `springboot`.`book`(`id`, `author`, `name`, `price`, `create_time`, `description`) VALUES (12, '金庸1535783672457', '笑傲江湖1535783672457', 30, '2018-09-01 14:34:32', '是做家金庸創做的一部長篇武俠小說1535783672457');
INSERT INTO `springboot`.`book`(`id`, `author`, `name`, `price`, `create_time`, `description`) VALUES (13, '金庸1535783673664', '笑傲江湖1535783673664', 30, '2018-09-01 14:34:34', '是做家金庸創做的一部長篇武俠小說1535783673664');
INSERT INTO `springboot`.`book`(`id`, `author`, `name`, `price`, `create_time`, `description`) VALUES (14, '金庸1535783939262', '笑傲江湖1535783939262', 30, '2018-09-01 14:38:59', '是做家金庸創做的一部長篇武俠小說1535783939262');

引入依賴

建立 Springboot 項目不提,引入 maven 依賴,主要是 mybastis 核心依賴以及 mybatis mapper 自動生成插件、分頁插件、通用 Mapper 插件。依賴中的 druid 數據源部分,能夠參考系列文章第九篇。web

<dependencies>
        <!-- Spring Boot web 開發整合 -->
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-web</artifactId>
            <exclusions>
                <exclusion>
                    <artifactId>spring-boot-starter-json</artifactId>
                    <groupId>org.springframework.boot</groupId>
                </exclusion>
            </exclusions>
        </dependency>

        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-test</artifactId>
            <scope>test</scope>
        </dependency>

        <!-- 阿里 fastjson -->
        <dependency>
            <groupId>com.alibaba</groupId>
            <artifactId>fastjson</artifactId>
            <version>1.2.47</version>
        </dependency>

        <!-- Lombok 工具 -->
        <dependency>
            <groupId>org.projectlombok</groupId>
            <artifactId>lombok</artifactId>
            <optional>true</optional>
        </dependency>

        <!-- 導入配置文件處理器,在配置springboot相關文件時候會有提示 -->
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-configuration-processor</artifactId>
            <optional>true</optional>
        </dependency>

        <!--添加數據庫連接 -->
        <dependency>
            <groupId>mysql</groupId>
            <artifactId>mysql-connector-java</artifactId>
        </dependency>

        <!-- Druid 數據源 -->
        <dependency>
            <groupId>com.alibaba</groupId>
            <artifactId>druid-spring-boot-starter</artifactId>
            <version>1.1.10</version>
        </dependency>

        <!-- mybatis -->
        <dependency>
            <groupId>org.mybatis.spring.boot</groupId>
            <artifactId>mybatis-spring-boot-starter</artifactId>
            <version>1.3.2</version>
        </dependency>

        <!-- mybatis mapper自動生成插件 -->
        <dependency>
            <groupId>org.mybatis.generator</groupId>
            <artifactId>mybatis-generator-core</artifactId>
            <version>1.3.7</version>
            <scope>compile</scope>
            <optional>true</optional>
        </dependency>

        <!-- mybatis pagehelper 分頁插件 -->
        <dependency>
            <groupId>com.github.pagehelper</groupId>
            <artifactId>pagehelper-spring-boot-starter</artifactId>
            <version>1.2.10</version>
        </dependency>
        <dependency>
            <groupId>tk.mybatis</groupId>
            <artifactId>mapper-spring-boot-starter</artifactId>
            <version>2.1.5</version>
        </dependency>

        <!-- mybatis 通用 Mapper -->
        <dependency>
            <groupId>tk.mybatis</groupId>
            <artifactId>mapper</artifactId>
            <version>4.0.4</version>
        </dependency>

    </dependencies>

簡單說明一下幾個不常見依賴的做用。spring

  1. mybatis-generator-core 用於自動生成 model、mapper 接口、mapper xml。
  2. pagehelper-spring-boot-starter 用於分頁
  3. mapper 用於加強增刪改查功能,集成了不少經常使用操做。

增長配置

關於 Druid 數據源的配置再也不說明,能夠參考系列文章第九篇。配置中主要配置了項目編碼、數據源信息、durid 數據源和 mybatis 的 mapper 位置以及 mybatis 映射別名的包路徑。還有 pagehelper 分頁插件部分。sql

############################################################
# 服務啓動端口號
server.port=8080
spring.profiles.active=dev
# 編碼
server.tomcat.uri-encoding=utf-8
spring.http.encoding.force=true
spring.http.encoding.charset=UTF-8
spring.http.encoding.enabled=true
############################################################
spring.datasource.url=jdbc:mysql://127.0.0.1:3306/springboot?characterEncoding=utf-8&serverTimezone=GMT%2B8
spring.datasource.driver-class-name=com.mysql.jdbc.Driver
spring.datasource.username=root
spring.datasource.password=123
# 使用 druid 數據源
spring.datasource.type:com.alibaba.druid.pool.DruidDataSource
spring.datasource.initialSize:5
spring.datasource.minIdle:5
spring.datasource.maxActive:20
spring.datasource.maxWait:60000
spring.datasource.timeBetweenEvictionRunsMillis:60000
spring.datasource.minEvictableIdleTimeMillis:300000
spring.datasource.validationQuery:SELECT 1 FROM DUAL
spring.datasource.testWhileIdle:true
spring.datasource.testOnBorrow:false
spring.datasource.testOnReturn:false
spring.datasource.poolPreparedStatements:true
spring.datasource.filters:stat
spring.datasource.maxPoolPreparedStatementPerConnectionSize:20
spring.datasource.useGlobalDataSourceStat:true
spring.datasource.connectionProperties:druid.stat.mergeSql=true;druid.stat.slowSqlMillis=500
############################################################
# mybatis
mybatis.mapper-locations=classpath:mapper/*.xml
mybatis.type-aliases-package=net.codingme.boot.domain
############## mybatis page配置#######################
# restart 類加載加載 include 進去的 jar 包。
restart.include.mapper=/mapper-[\\w-\\.]+jar
restart.include.pagehelper=/pagehelper-[\\w-\\.]+jar
# mappers 多個接口時逗號隔開
mapper.mappers=net.codingme.boot.util.MybatisMapper
mapper.not-empty=false
mapper.identity=MYSQL
# pagehelper
pagehelper.helperDialect=mysql
pagehelper.reasonable=true
pagehelper.supportMethodsArguments=true
pagehelper.params=count=countSql
# 輸出 mybatis SQL 日誌
logging.level.net.codingme.boot.domain.mapper=debug

一些說明。數據庫

  1. mapper.mappers=net.codingme.boot.util.MybatisMapper 用於包含一個本身編寫的 mapper。
  2. restart.include 熱部署
  3. logging.level.net.codingme.boot.domain.mapper=debug 輸出 Mybatis SQL 這裏要指定本身 mapper 所在的包路徑

通用 Mapper

在上一篇文章中也演示了自動生成,那是通用的一種生成方式,此次咱們引入通用 Mapper 再進行生成,這樣生成的代碼更加簡潔。json

爲了方便理解,先看一下項目最終結構。

自動生成配置

自動生成通用接口分爲兩步,第一步是編寫生成配置文件,註釋已經添加了,直接看代碼。

<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE generatorConfiguration
        PUBLIC "-//mybatis.org//DTD MyBatis Generator Configuration 1.0//EN"
        "http://mybatis.org/dtd/mybatis-generator-config_1_0.dtd">

<generatorConfiguration>
    <context id="MysqlContext" targetRuntime="MyBatis3Simple" defaultModelType="flat">
        <property name="beginningDelimiter" value="`"/>
        <property name="endingDelimiter" value="`"/>
        <property name="javaFileEncoding" value="UTF-8"/>
        <!-- 是否使用通用 Mapper 提供的註釋工具,默認 true 使用,這樣在生成代碼時會包含字段的註釋(目前只有 mysql 和 oracle 支持)-->
        <property name="useMapperCommentGenerator" value="true"/>

        <plugin type="tk.mybatis.mapper.generator.MapperPlugin">
            <!-- 配置後生成的 Mapper 接口都會自動繼承這個接口-->
            <property name="mappers" value="tk.mybatis.mapper.common.MySqlMapper"/>
        </plugin>

        <plugin type="tk.mybatis.mapper.generator.MapperPlugin">
            <!-- 配置後生成的 Mapper 接口都會自動繼承這個接口 -->
            <property name="mappers" value="tk.mybatis.mapper.common.Mapper"/>
            <!-- 是否區分大小寫,默認 false -->
            <property name="caseSensitive" value="true"/>
        </plugin>

        <jdbcConnection driverClass="com.mysql.cj.jdbc.Driver"
                        connectionURL="jdbc:mysql://127.0.0.1:3306/springboot?characterEncoding=utf-8&amp;serverTimezone=GMT%2B8&amp;nullCatalogMeansCurrent=true"
                        userId="root"
                        password="123">
        </jdbcConnection>

        <!-- 對於生成的pojo所在包 -->
        <javaModelGenerator targetPackage="net.codingme.boot.domain" targetProject="src/main/java"/>

        <!-- 對於生成的mapper所在目錄 -->
        <sqlMapGenerator targetPackage="mapper" targetProject="src/main/resources"/>

        <!-- 配置mapper對應的java映射 -->
        <javaClientGenerator targetPackage="net.codingme.boot.domain.mapper" targetProject="src/main/java"
                             type="XMLMAPPER"/>

        <!-- 要生成那些表(更改tableName和domainObjectName就能夠) -->
        <table tableName="book" domainObjectName="Book"/>

    </context>
</generatorConfiguration>

與上次不一樣的是此次增長了兩個 plugin,後面生成的 Mapper 接口都會自動繼承這些類。

自動生成代碼

寫好配置文件以後,還須要寫一個生成程序,用於加載配置文件,運行就能夠生成相關的實體類、Mapper 接口、Mapper xml .

import org.mybatis.generator.api.MyBatisGenerator;
import org.mybatis.generator.config.Configuration;
import org.mybatis.generator.config.xml.ConfigurationParser;
import org.mybatis.generator.internal.DefaultShellCallback;
import java.io.File;
import java.util.ArrayList;
/**
 * <p>
 * Mybatis generator的逆向生成工具類
 *
 * @Author niujinpeng
 */
public class MybatisGenerator {

    public void generator() throws Exception {
        ArrayList<String> warnings = new ArrayList<>();
        boolean overwrite = true;
        // 指定你想工程配置文件
        File configFile = new File("generatorConfig.xml");
        System.out.println(configFile.getAbsolutePath());
        ConfigurationParser cp = new ConfigurationParser(warnings);
        Configuration config = cp.parseConfiguration(configFile);
        DefaultShellCallback callback = new DefaultShellCallback(overwrite);
        MyBatisGenerator myBatisGenerator = new MyBatisGenerator(config, callback, warnings);
        myBatisGenerator.generate(null);
        for (String warning : warnings) {
            System.out.println(warning);
        }
    }

    public static void main(String[] args) throws Exception {
        MybatisGenerator mybatisGenerator = new MybatisGenerator();
        mybatisGenerator.generator();
    }
}

自動生成結果

運行完畢上面程序以後,自動生成了 Book.java.

@Table(name = "book")
@ToString // 手動添加的 tostring 註解
public class Book {
    @Id
    private Integer id;

    /**
     * 書籍做者
     */
    private String author;

    /**
     * 書籍名稱
     */
    private String name;

    /**
     * 書籍價格
     */
    private Float price;

    // 省略下面的自動生成代碼

通用 Mapper

上面的程序也自動生成了 BookMapper 接口,且繼承了配置的 MySqlMapper 和 Mapper 接口。

import net.codingme.boot.domain.Book;
import org.springframework.stereotype.Repository;
import tk.mybatis.mapper.common.Mapper;
import tk.mybatis.mapper.common.MySqlMapper;

@Repository
public interface BookMapper extends MySqlMapper<Book>, Mapper<Book> {
}

這兩個接口裏實現了不少經常使用操做。

生成完成以後要在 Springboot 啓動器上添加 MapperScan 註解指定要掃描的 mapper 位置。

@tk.mybatis.spring.annotation.MapperScan(basePackages = "net.codingme.boot.domain.mapper")
@SpringBootApplication
public class BootApplication {

    public static void main(String[] args) {
        SpringApplication.run(BootApplication.class, args);
    }
}

單元測試和分頁測試

編寫 BookMapperTest 單元測試用於測試 BookMapper 的方法。

package net.codingme.boot.domain.mapper;

import com.github.pagehelper.Page;
import com.github.pagehelper.PageHelper;
import com.github.pagehelper.PageInfo;
import net.codingme.boot.domain.Book;
import org.junit.Assert;
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.util.List;

@RunWith(SpringRunner.class)
@SpringBootTest
public class BookMapperTest {

    @Autowired
    private BookMapper bookMapper;

    @Test
    public void testSelectOne() {
        Book book = new Book();
        book.setId(2);
        Book selectOne = bookMapper.selectOne(book);
        Assert.assertNotNull(selectOne);
        System.out.println(selectOne);
    }

    @Test
    public void testSelectByPrimaryKey() {
        Book book = bookMapper.selectByPrimaryKey(2);
        Assert.assertNotNull(book);
        System.out.println(book);
    }

    /**
     * 分頁測試
     */
    @Test
    public void testSelectPageInfo() {
        PageHelper.startPage(2, 3);
        List<Book> bookList = bookMapper.selectAll();
        Assert.assertNotNull(bookList);
        System.out.println("查詢出數量:" + bookList.size());
        PageInfo<Book> pageInfo = PageInfo.of(bookList);
        System.out.println("總數量:" + pageInfo.getTotal());
        System.out.println("總頁數:" + pageInfo.getPages());
        System.out.println("頁大小:" + pageInfo.getPageSize());
        System.out.println("第幾頁:" + pageInfo.getPageNum());
        System.out.println("當前量:" + pageInfo.getSize());
    }

    /**
     * 分頁測試
     */
    @Test
    public void testSelectPage() {
        PageHelper.startPage(2, 3);
        List<Book> bookList = bookMapper.selectAll();
        Assert.assertNotNull(bookList);
        System.out.println("查詢出數量:" + bookList.size());
        System.out.println("總數量:" + ((Page)bookList).getTotal());
        System.out.println("總頁數:" + ((Page)bookList).getPages());
        System.out.println("第幾頁:" + ((Page)bookList).getPageNum());
    }

}

從代碼中能夠看到分頁的實現主要是 PageHelper 的設置,在設置 PageHelper 以後的第一個查詢會進行分頁。像上面的例子會查詢第二頁,每頁三條這樣。

PageHelper.startPage(2, 3);
List<Book> bookList = bookMapper.selectAll();

其實使用了分頁插件以後返回的數據類型是一個 Page 類,總數等分頁信息都已經返回,若是要取出來使用就須要強制轉換類型而後取出,上面也是演示了兩種方式。

// 方式 1
PageInfo<Book> pageInfo = PageInfo.of(bookList);
System.out.println("總數量:" + pageInfo.getTotal());
System.out.println("總頁數:" + pageInfo.getPages());
System.out.println("頁大小:" + pageInfo.getPageSize());
System.out.println("第幾頁:" + pageInfo.getPageNum());
System.out.println("當前量:" + pageInfo.getSize());

// 方式 2
System.out.println("查詢出數量:" + bookList.size());
System.out.println("總數量:" + ((Page)bookList).getTotal());
System.out.println("總頁數:" + ((Page)bookList).getPages());
System.out.println("第幾頁:" + ((Page)bookList).getPageNum());

運行 BookMapperTest 類測試全部的單元測試。

發現單元測試所有經過,查看一個分頁查詢(testSelectPageInfo)輸出狀況。

2019-03-08 16:07:52.226 DEBUG 26764 --- [           main] n.c.b.d.m.BookMapper.selectAll_COUNT     : ==>  Preparing: SELECT count(0) FROM book 
2019-03-08 16:07:52.227 DEBUG 26764 --- [           main] n.c.b.d.m.BookMapper.selectAll_COUNT     : ==> Parameters: 
2019-03-08 16:07:52.229 DEBUG 26764 --- [           main] n.c.b.d.m.BookMapper.selectAll_COUNT     : <==      Total: 1
2019-03-08 16:07:52.231 DEBUG 26764 --- [           main] n.c.b.d.mapper.BookMapper.selectAll      : ==>  Preparing: SELECT id,author,name,price,create_time,description FROM book LIMIT ?, ? 
2019-03-08 16:07:52.233 DEBUG 26764 --- [           main] n.c.b.d.mapper.BookMapper.selectAll      : ==> Parameters: 3(Integer), 3(Integer)
2019-03-08 16:07:52.236 DEBUG 26764 --- [           main] n.c.b.d.mapper.BookMapper.selectAll      : <==      Total: 3
查詢出數量:3
總數量:12
總頁數:4
頁大小:3
第幾頁:2
當前量:3

再查看一個普通查詢(testSelectByPrimaryKey)輸出狀況。

2019-03-08 16:07:52.241 DEBUG 26764 --- [           main] n.c.b.d.m.BookMapper.selectByPrimaryKey  : ==>  Preparing: SELECT id,author,name,price,create_time,description FROM book WHERE id = ? 
2019-03-08 16:07:52.242 DEBUG 26764 --- [           main] n.c.b.d.m.BookMapper.selectByPrimaryKey  : ==> Parameters: 2(Integer)
2019-03-08 16:07:52.244 DEBUG 26764 --- [           main] n.c.b.d.m.BookMapper.selectByPrimaryKey  : <==      Total: 1
Book(id=2, author=金庸, name=笑傲江湖, price=12.0, createTime=Sat Sep 01 10:10:12 GMT+08:00 2018, description=是做家金庸創做的一部長篇武俠小說)

文中代碼已經上傳到 Github Spring Boot 鏈接數據庫 - Mybatis 插件

想要了解這幾個插件的其餘信息,能夠查看官方文檔。

  1. 如何使用分頁插件
  2. Mapper插件
  3. MyBatis Generator

<div id="MySignature" style="max-width:500px;display: block;border: solid 1px #E5E5E5;padding: 10px; background: #FFFEFE url(https://img2018.cnblogs.com/blog/1202902/201908/1202902-20190806114612975-1863336558.png) no-repeat scroll 1% 50%; padding-left: 180px;height: 160px;"> <div style="padding-top: 10px;">本文做者:<b>雪漫士兵</b><br> 個人微信:wn8398<br> 原文出處:<a href="https://www.codingme.net">www.codingme.net</a> <!-- 交流羣號:139267796 <br> --> <div style="margin-top:10px;margin-bottom:5px;">本片文章是博主原創文章,歡迎轉載,轉載時在明顯位置註明原文連接便可。</div> <b>若是以爲這篇內容有趣好玩有幫助,不妨關注公衆號點個好看推薦。</b> </div> <div style="clear: both"></div> </div>

原文出處:https://www.cnblogs.com/niumoo/p/10496753.html

相關文章
相關標籤/搜索