springboot2集成mybatis-plus

一. MyBatis-Plus簡介

簡介:

MyBatis-Plus(簡稱 MP)是一個 MyBatis 的增強工具,在 MyBatis 的基礎上只做增強不做改變,爲簡化開發、提高效率而生。
另最新的3.x版本支持lambda()語法糖, 方便以代碼方式組織SQL語句.
在這裏插入圖片描述

核心特性

賣點 說明
無侵入 只做增強不做改變,引入它不會對現有工程產生影響,如絲般順滑
損耗小 啓動即會自動注入基本 CURD,性能基本無損耗,直接面向對象操作
強大的 CRUD 操作 內置通用 Mapper、通用 Service,僅僅通過少量配置即可實現單表大部分 CRUD 操作,更有強大的條件構造器,滿足各類使用需求
支持 Lambda 形式調用 通過 Lambda 表達式,方便的編寫各類查詢條件,無需再擔心字段寫錯
支持主鍵自動生成 支持多達 4 種主鍵策略(內含分佈式唯一 ID 生成器 - Sequence),可自由配置,完美解決主鍵問題
支持 ActiveRecord 模式 支持 ActiveRecord 形式調用,實體類只需繼承 Model 類即可進行強大的 CRUD 操作
支持自定義全局通用操作 支持全局通用方法注入( Write once, use anywhere )
內置代碼生成器 採用代碼或者 Maven 插件可快速生成 Mapper 、 Model 、 Service 、 Controller 層代碼,支持模板引擎,更有超多自定義配置等您來使用
內置分頁插件 基於 MyBatis 物理分頁,開發者無需關心具體操作,配置好插件之後,寫分頁等同於普通 List 查詢
分頁插件支持多種數據庫 支持 MySQL、MariaDB、Oracle、DB2、H2、HSQL、SQLite、Postgre、SQLServer 等多種數據庫
內置性能分析插件 可輸出 Sql 語句以及其執行時間,建議開發測試時啓用該功能,能快速揪出慢查詢
內置全局攔截插件 提供全表 delete 、 update 操作智能分析阻斷,也可自定義攔截規則,預防誤操作

支持數據庫

mysql 、 mariadb 、 oracle 、 db2 、 h2 、 hsql 、 sqlite 、 postgresql 、 sqlserver
達夢數據庫 、 虛谷數據庫 、 人大金倉數據庫

MP框架結構

在這裏插入圖片描述

代碼託管

Gitee | Github

學習教程

官方教程:

非官方視頻教程:

  1. MyBatis-Plus 入門 - 視頻教程 - 慕課網
  2. MyBatis-Plus 進階 - 視頻教程 - 慕課網

二. springboot2集成mybatis-plus

2.1 項目構建

傳送門: -IDEA創建SpringBoot項目

2.2 項目環境

軟件 版本
JDK 1.8
SpringBoot 2.2.6.RELEASE
MyBatis-Plus 3.1.0

2.3 項目結構

在這裏插入圖片描述

2.4 pom.xml

<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
	xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 https://maven.apache.org/xsd/maven-4.0.0.xsd">
	<modelVersion>4.0.0</modelVersion>
	<parent>
		<groupId>org.springframework.boot</groupId>
		<artifactId>spring-boot-starter-parent</artifactId>
		<version>2.2.6.RELEASE</version>
		<relativePath/> <!-- lookup parent from repository -->
	</parent>
	<groupId>com.example</groupId>
	<artifactId>mybatisplus</artifactId>
	<version>0.0.1-SNAPSHOT</version>
	<name>springboot_mybatisplus</name>
	<description>Demo project for Spring Boot</description>

	<properties>
		<java.version>1.8</java.version>
	</properties>

	<dependencies>
		<dependency>
			<groupId>org.springframework.boot</groupId>
			<artifactId>spring-boot-starter-web</artifactId>
		</dependency>
		<dependency>
			<groupId>mysql</groupId>
			<artifactId>mysql-connector-java</artifactId>
			<!--<version>5.1.47</version>-->
			<scope>runtime</scope>
		</dependency>
		<dependency>
			<groupId>org.projectlombok</groupId>
			<artifactId>lombok</artifactId>
			<optional>true</optional>
		</dependency>
		<dependency>
			<groupId>org.springframework.boot</groupId>
			<artifactId>spring-boot-starter-test</artifactId>
			<scope>test</scope>
		</dependency>
		<!-- mybatisPlus 核心庫 -->
		<dependency>
			<groupId>com.baomidou</groupId>
			<artifactId>mybatis-plus-boot-starter</artifactId>
			<version>3.1.0</version>
		</dependency>
		<!-- 引入阿里數據庫連接池 -->
		<dependency>
			<groupId>com.alibaba</groupId>
			<artifactId>druid</artifactId>
			<version>1.1.6</version>
		</dependency>
		<dependency>
			<groupId>org.springframework.boot</groupId>
			<artifactId>spring-boot-starter-test</artifactId>
			<scope>test</scope>
		</dependency>
		<!--swagger start-->
		<dependency>
			<groupId>io.springfox</groupId>
			<artifactId>springfox-swagger2</artifactId>
			<version>2.9.2</version>
		</dependency>
		<dependency>
			<groupId>io.springfox</groupId>
			<artifactId>springfox-swagger-ui</artifactId>
			<version>2.9.2</version>
		</dependency>
		<!--swagger  end-->
	</dependencies>

	<build>
		<plugins>
			<plugin>
				<groupId>org.springframework.boot</groupId>
				<artifactId>spring-boot-maven-plugin</artifactId>
			</plugin>
		</plugins>
	</build>

</project>

2.5 springboot2 配置文件

# 配置端口
server:
  port: 8080 
spring:
  # 配置數據源
  datasource:
    driver-class-name: com.mysql.cj.jdbc.Driver
    url: jdbc:mysql://{IP}:{PORT}/user?useUnicode=true&characterEncoding=UTF-8&autoReconnect=true&useSSL=false&zeroDateTimeBehavior=convertToNull
    username: xxxx
    password: xxxx
    type: com.alibaba.druid.pool.DruidDataSource
# mybatis 相關 configurations
mybatis-plus:
  # xml掃描,多個目錄用逗號或者分號分隔(告訴 Mapper 所對應的 XML 文件位置)
  mapper-locations: classpath:mapper/*.xml
  # 以下配置均有默認值,可以不設置
  global-config:
    db-config:
      # 主鍵類型,大小寫不敏感 AUTO:"數據庫ID自增", INPUT:"用戶輸入ID", ID_WORKER:"全局唯一ID (數字類型唯一ID)", UUID:"全局唯一ID UUID"
      id-type: auto
      # 字段策略 IGNORED:"忽略判斷"  NOT_NULL:"非 NULL 判斷")  NOT_EMPTY:"非空判斷"
      field-strategy: not_empty
      #數據庫類型, 大小寫不敏感
      db-type: mysql
  configuration:
    # 是否開啓自動駝峯命名規則映射:從數據庫列名到Java屬性駝峯命名的類似映射
    map-underscore-to-camel-case: true
    # 如果查詢結果中包含空值的列,則 MyBatis 在映射的時候,不會映射這個字段
    call-setters-on-nulls: true
    # 這個配置會將執行的sql打印出來,在開發或測試的時候可以用
    log-impl: org.apache.ibatis.logging.stdout.StdOutImpl

2.6 構建測試data

-- 建表
CREATE TABLE `user_info` (
  `id` bigint(11) NOT NULL AUTO_INCREMENT COMMENT 'ID',
  `name` varchar(32) DEFAULT NULL COMMENT '姓名',
  `age` int(11) DEFAULT NULL COMMENT '年齡',
  `skill` varchar(32) DEFAULT NULL COMMENT '技能',
  `evaluate` varchar(64) DEFAULT NULL COMMENT '評價',
  `fraction` bigint(11) DEFAULT NULL COMMENT '分數',
  PRIMARY KEY (`id`)
) ENGINE=InnoDB AUTO_INCREMENT=16 DEFAULT CHARSET=utf8mb4 COMMENT='學生信息表';

-- 插入數據
INSERT INTO `user_info` VALUES (1, '小明', 20, '畫畫', '該學生在畫畫方面有一定天賦', 89);
INSERT INTO `user_info` VALUES (2, '小蘭', 19, '遊戲', '近期該學生由於遊戲的原因導致分數降低了', 64);
INSERT INTO `user_info` VALUES (3, '張張', 18, '英語', '近期該學生參加英語比賽獲得二等獎', 90);
INSERT INTO `user_info` VALUES (4, '大黃', 20, '體育', '該學生近期由於參加籃球比賽,導致腳傷', 76);
INSERT INTO `user_info` VALUES (5, '大白', 17, '繪畫', '該學生參加美術大賽獲得三等獎', 77);
INSERT INTO `user_info` VALUES (7, '小龍', 18, 'JAVA', '該學生是一個在改BUG的碼農', 59);
INSERT INTO `user_info` VALUES (9, 'Sans', 18, '睡覺', 'Sans是一個愛睡覺,並且身材較矮骨骼巨大的骷髏小胖子', 60);
INSERT INTO `user_info` VALUES (10, 'papyrus', 18, 'JAVA', 'Papyrus是一個講話大聲、個性張揚的骷髏,給人自信、有魅力的骷髏小瘦子', 58);
INSERT INTO `user_info` VALUES (11, '刪除數據1', 3, '畫肖像', NULL, 61);
INSERT INTO `user_info` VALUES (12, '刪除數據2', 3, NULL, NULL, 61);
INSERT INTO `user_info` VALUES (13, '刪除數據3', 3, NULL, NULL, 61);
INSERT INTO `user_info` VALUES (14, '刪除數據4', 5, '刪除', NULL, 10);
INSERT INTO `user_info` VALUES (15, '刪除數據5', 6, '刪除', NULL, 10);

2.7 編寫類

①. SpringBoot2 啓動類

Usage:
加載Spring容器上下文, 解析配置文件, 解析註解, 反射進行Object生成, DI依賴注入等.

注意:
spring boot 可以管理同級目錄下的註解, 也可以管理下級目錄的註解, 如果位置不對,可以用@ComponentScan(basePackages = {"","",""})去定義包的位置,但是如果使用該方法,spring boot 就不能再去訪問同級目錄,或者未定義包位置的下級目錄.

具體到開發中, 需要注意:

  1. 啓動類不能放置在main/java下.
  2. 啓動類不能放置在下級目錄中. 如dao/service等package中.
package com.example;

import org.mybatis.spring.annotation.MapperScan;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;

@SpringBootApplication
@MapperScan(basePackages = {"com.example.dao"})
@EnableSwagger2
public class MybatisPlusDemoApplication {

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

}

②. MyBatis-Plus 配置類

Usage:
MyBatis-Plus 配置增強選項, 實現以下功能:
- 1.debug等開發環境下,提供SQL執行效率的輸出信息, 幫助檢查優化sql, 揪出slow query問題.
- 2.簡易的代碼, 提供強大的分頁Page查詢功能.

package com.example.config;

import com.baomidou.mybatisplus.extension.plugins.PaginationInterceptor;
import com.baomidou.mybatisplus.extension.plugins.PerformanceInterceptor;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;

/**
 * User: Administrator
 * Date: 2020/4/7
 * Time: 16:00
 * Desc: 
 */
@Configuration
public class MybatisPlusConfig {

    /**
     * mybatis-plus SQL執行效率插件【生產環境可以關閉】
     */
    @Bean
    public PerformanceInterceptor performanceInterceptor() {
        return new PerformanceInterceptor();
    }

    /**
     * 分頁插件
     */
    @Bean
    public PaginationInterceptor paginationInterceptor() {
        return new PaginationInterceptor();
    }

}

③. Entity實例類

Usage: 實體Pojo類構建, 對象封裝, 數據承載

package com.example.entity;

import com.baomidou.mybatisplus.annotation.IdType;
import com.baomidou.mybatisplus.annotation.TableId;
import com.baomidou.mybatisplus.annotation.TableName;

/**
 * User: Administrator
 * Date: 2020/4/7
 * Time: 16:03
 * Desc:
 */
@Data //lombok提供簡單的實體Pojo類構建
@TableName("user_info") // @TableName中的值, 對應着數據庫中的表名
public class UserInfoEntity {

     /**
     * 主鍵
     * @TableId中可以決定主鍵的類型,不寫會採取默認值,默認值可以在yml中配置
     * AUTO: 數據庫ID自增
     * INPUT: 用戶輸入ID
     * ID_WORKER: 全局唯一ID,Long類型的主鍵
     * ID_WORKER_STR: 字符串全局唯一ID
     * UUID: 全局唯一ID,UUID類型的主鍵
     * NONE: 該類型爲未設置主鍵類型
     */
    @TableId(type = IdType.AUTO)
    private Long id;

    /**
     * 姓名
     */
    private String name;
    /**
     * 年齡
     */
    private Integer age;
    /**
     * 技能
     */
    private String skill;
    /**
     * 評價
     */
    private String evaluate;
    /**
     * 分數
     */
    private Long fraction;

}

④. Dao層接口

Usage:
該接口繼承了BaseMapper<EntityObject>, 集成了基礎的CURD功能.

說明:

  • 1.如上所述, 無須做複雜配置或寫DbUtils工具, 即可進行基礎的CURD操作(如果僅實現CURD功能, 此接口甚至無法定義任何方法, 即可開箱即用; 本接口中定義的方法爲所謂的"複雜業務"服務, 無須添加此方法,簡單CURD操作即可完成操作);
  • 2.複雜的sql邏輯, 提供傳統的xxxMapper.xml映射文件支持;
  • 3.注意:接口方法第二個參數fraction前, 需加上註解@Param("fraction"), 將入參與xxxMapper.xml中的如下紅色部分的parameterType入參類型相匹配, 否則將會報錯:"nested exception is org.apache.ibatis.binding.BindingException: Parameter 'fraction' not found. Available parameters are [arg1, arg0, param1, param2]".

<select id=“selectUserInfoByGtFraction” resultType=“com.example.entity.UserInfoEntity” parameterType="long">

注意:
很多開發者dao層習慣於命名爲mapper層, 道理是一樣的, 相應的, 接口名UserInfoDao 需要 同步調整爲 UserInfoMapper.

package com.example.dao;

import com.baomidou.mybatisplus.core.mapper.BaseMapper;
import com.baomidou.mybatisplus.core.metadata.IPage;
import com.example.entity.UserInfoEntity;

/**
 * User: Administrator
 * Date: 2020/4/7
 * Time: 16:06
 * Desc: 用戶信息DAO
 */
public interface UserInfoDao extends BaseMapper<UserInfoEntity> {


    /**
     * 查詢大於該分數的學生
     * @Param  page  分頁參數
     * @Param  fraction  分數
     * @Return IPage<UserInfoEntity> 分頁數據
     */
    IPage<UserInfoEntity> selectUserInfoByGtFraction(IPage<UserInfoEntity> page, @Param("fraction") Long fraction);

}

⑤. service接口

Usage:
用戶業務接口類的接口定義, 用於定義非基礎CURD的"複雜業務邏輯"方法定義.

5.1 service: 接口定義

類定義模板:
interface BIZService extends IService<BIZEntity>
其中:
IService<BIZEntity> 爲 框架中類.

package com.example.service;

import com.baomidou.mybatisplus.core.metadata.IPage;
import com.baomidou.mybatisplus.extension.service.IService;
import com.example.entity.UserInfoEntity;

/**
 * User: Administrator
 * Date: 2020/4/7
 * Time: 16:06
 * Desc: 用戶業務接口
 */
public interface UserInfoService extends IService<UserInfoEntity> {

    /**
     * 查詢大於該分數的學生
     * @Param  page  分頁參數
     * @Param  fraction  分數
     * @Return IPage<UserInfoEntity> 分頁數據
     */
    IPage<UserInfoEntity> selectUserInfoByGtFraction(IPage<UserInfoEntity> page, Long fraction);
}

5.2 serviceImpl: 接口實現類

類定義模板:
BIZSerivceImpl extends ServiceImpl<BIZDao, BIZEntity> implements BIZService
其中:
ServiceImpl<BIZDao, BIZEntity> 爲 框架中類.

package com.example.service.impl;

import com.baomidou.mybatisplus.core.metadata.IPage;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.example.dao.UserInfoDao;
import com.example.service.UserInfoService;
import com.example.entity.UserInfoEntity;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

/**
 * User: Administrator
 * Date: 2020/4/7
 * Time: 16:20
 * Desc: 用戶業務實現
 */
@Service
@Transactional
public class UserInfoSerivceImpl extends ServiceImpl<UserInfoDao, UserInfoEntity> implements UserInfoService{

    /**
     * 查詢大於該分數的學生
     * @Param  page  分頁參數
     * @Param  fraction  分數
     * @Return IPage<UserInfoEntity> 分頁數據
     */
    @Override
    public IPage<UserInfoEntity> selectUserInfoByGtFraction(IPage<UserInfoEntity> page, Long fraction) {
        return this.baseMapper.selectUserInfoByGtFraction(page, fraction);
    }
}

⑥. controller 類

Usage:
控制層的作用:接收客戶端的請求,然後調用Service層業務邏輯,獲取到數據,傳遞數據給視圖層(客戶端)用於視覺呈現.

6.1 MyBatis-Plus 基礎CURD功能Demo

Usage:
這裏我們看到,service中我們沒有寫任何方法,MyBatis-Plus官方封裝了許多基本CRUD的方法,可以直接使用大量節約時間,MyBatis-Plus共通方法詳見IService,ServiceImpl,BaseMapper源碼,寫入操作在ServiceImpl中已有事務綁定,這裏我們舉一些常用的方法演示.

package com.example.controller;

import com.baomidou.mybatisplus.core.metadata.IPage;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.example.service.UserInfoService;
import com.example.entity.UserInfoEntity;
import io.swagger.annotations.ApiOperation;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.RequestBody;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;

import java.util.*;

/**
 * User: Administrator
 * Date: 2020/4/7
 * Time: 16:23
 * Desc: MP基礎CURD功能DEMO
 */
@RestController
@RequestMapping("/userInfo")
public class UserInfoController {

    @Autowired
    private UserInfoService userInfoService;
     
    /**
     * 根據ID獲取用戶信息
     * TODO
     * /
    @ApiOperation("根據用戶ID獲取用戶信息")
    @PostMapping("/getInfo")
    public UserInfoEntity getInfo(@RequestBody String userId){
        UserInfoEntity userInfoEntity = userInfoService.getById(userId);
        return userInfoEntity;
    }

    /**
     * 根據ID獲取用戶信息
     * /
    @ApiOperation("查詢全部信息")
    @PostMapping("/getList")
    public List<UserInfoEntity> getList(){
        List<UserInfoEntity> list = userInfoService.list();
        return list;
    }

    /**
     * 分頁查詢全部數據
     * @Return IPage<UserInfoEntity> 分頁數據
     */
    @ApiOperation("分頁查詢全部數據")
    @PostMapping("/getInfoListPage")
    public IPage<UserInfoEntity> getInfoListPage(){
        //需要在Config配置類中配置分頁插件
        IPage<UserInfoEntity> page = new Page<>();
        page.setCurrent(1); //當前頁
        page.setSize(5);    //每頁條數
        page = userInfoService.page(page);
        return page;
    }
    
    /**
     * 根據指定字段查詢用戶信息集合
     * @Return Collection<UserInfoEntity> 用戶實體集合
     */
    @ApiOperation("根據指定字段查詢用戶信息集合")
    @PostMapping("/getListMap")
    public Collection<UserInfoEntity> getListMap(){
        Map<String,Object> map = new HashMap<>();
        //kay是字段名 value是字段值
        map.put("age",20);
        Collection<UserInfoEntity> userInfoEntityList = userInfoService.listByMap(map);
        return userInfoEntityList;
    }
    
    /**
     * 新增用戶信息
     */
    @ApiOperation("新增用戶信息")
    @PostMapping("/saveInfo")
    public void saveInfo(){
        UserInfoEntity userInfoEntity = new UserInfoEntity();
        userInfoEntity.setName("小龍");
        userInfoEntity.setSkill("JAVA");
        userInfoEntity.setAge(18);
        userInfoEntity.setFraction(59L);
        userInfoEntity.setEvaluate("該學生是一個在改BUG的碼農");
        userInfoService.save(userInfoEntity);
    }
    
    /**
     * 批量新增用戶信息
     */
    @ApiOperation("批量新增用戶信息")
    @PostMapping("/saveInfoList")
    public void saveInfoList(){
        //創建對象
        UserInfoEntity sans = new UserInfoEntity();
        sans.setName("Sans");
        sans.setSkill("睡覺");
        sans.setAge(18);
        sans.setFraction(60L);
        sans.setEvaluate("Sans是一個愛睡覺,並且身材較矮骨骼巨大的骷髏小胖子");
        UserInfoEntity papyrus = new UserInfoEntity();
        papyrus.setName("papyrus");
        papyrus.setSkill("JAVA");
        papyrus.setAge(18);
        papyrus.setFraction(58L);
        papyrus.setEvaluate("Papyrus是一個講話大聲、個性張揚的骷髏,給人自信、有魅力的骷髏小瘦子");
        //批量保存
        List<UserInfoEntity> list =new ArrayList<>();
        list.add(sans);
        list.add(papyrus);
        userInfoService.saveBatch(list);
    }
    
    /**
     * 更新用戶信息
     */
    @ApiOperation("更新用戶信息")
    @PostMapping("/updateInfo")
    public void updateInfo(){
        //根據實體中的ID去更新,其他字段如果值爲null則不會更新該字段,參考yml配置文件
        UserInfoEntity userInfoEntity = new UserInfoEntity();
        userInfoEntity.setId(1L);
        userInfoEntity.setAge(19);
        userInfoService.updateById(userInfoEntity);
    }
    
    /**
     * 新增或者更新用戶信息
     */
    @ApiOperation("新增或者更新用戶信息")
    @PostMapping("/saveOrUpdateInfo")
    public void saveOrUpdate(){
        //傳入的實體類userInfoEntity中ID爲null就會新增(ID自增)
        //實體類ID值存在,如果數據庫存在ID就會更新,如果不存在就會新增
        UserInfoEntity userInfoEntity = new UserInfoEntity();
        userInfoEntity.setId(1L);
        userInfoEntity.setAge(20);
        userInfoService.saveOrUpdate(userInfoEntity);
    }
    
    /**
     * 根據ID刪除用戶信息
     */
    @ApiOperation("根據ID刪除用戶信息")
    @PostMapping("/deleteInfo")
    public void deleteInfo(String userId){
        userInfoService.removeById(userId);
    }
    
    /**
     * 根據ID批量刪除用戶信息
     */
    @ApiOperation("根據ID批量刪除用戶信息")
    @PostMapping("/deleteInfoList")
    public void deleteInfoList(){
        List<String> userIdlist = new ArrayList<>();
        userIdlist.add("12");
        userIdlist.add("13");
        userInfoService.removeByIds(userIdlist);
    }
    
    /**
     * 根據指定字段刪除用戶信息
     */
    @ApiOperation("根據指定字段刪除用戶信息")
    @PostMapping("/deleteInfoMap")
    public void deleteInfoMap(){
        //kay是字段名 value是字段值
        Map<String,Object> map = new HashMap<>();
        map.put("skill","刪除");
        map.put("fraction",10L);
        userInfoService.removeByMap(map);
    }
    
}

6.2 MyBatis-Plus 中 QueryWrapper條件構造器功能Demo

Usage:
當查詢條件複雜的時候,我們可以使用MP的條件構造器,請參考下面的QueryWrapper條件參數說明.

package com.example.controller;

import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.baomidou.mybatisplus.core.metadata.IPage;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.example.entity.UserInfoEntity;
import com.example.service.UserInfoService;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;

import java.util.HashMap;
import java.util.List;
import java.util.Map;

/**
 * User: Administrator
 * Date: 2020/4/7
 * Time: 19:14
 * Desc:  MP 提供的QueryWrapper條件選擇器功能DEMO
 */
@RestController
@RequestMapping("/userInfoPlus")
public class UserInfoPlusController {

    @Autowired
    private UserInfoService userInfoService;

    @RequestMapping("/getInfoListPlus")
    public Map<String, Object> getInfoListPage() {
        //初始化返回類
        Map<String, Object> result = new HashMap<>(100);

        //查詢年齡等於18的學生
        //等價sql: SELECT id,name,age,skill,evaluate,fraction FROM user_info WHERE age=18;
        QueryWrapper<UserInfoEntity> queryWrapper1 = new QueryWrapper<>();
        queryWrapper1.lambda().eq(UserInfoEntity::getAge, 18);
        List<UserInfoEntity> userInfoEntityList1 = userInfoService.list(queryWrapper1);
        result.put("studentAge18", userInfoEntityList1);

        //查詢年齡大於5歲的學生且小於等於18歲的學生
        //等價SQL: SELECT id,name,age,skill,evaluate,fraction FROM user_info WHERE age > 5 AND age <= 18
        QueryWrapper<UserInfoEntity> queryWrapper2 = new QueryWrapper<>();
        queryWrapper2.lambda().ge(UserInfoEntity::getAge, 5);
        queryWrapper2.lambda().le(UserInfoEntity::getAge, 18);
        List<UserInfoEntity> userInfoEntityList2 = userInfoService.list(queryWrapper2);
        result.put("studentAge5", userInfoEntityList2);

        //模糊查詢技能字段帶有"畫"的數據,並按照年齡降序
        //等價SQL: SELECT id,name,age,skill,evaluate,fraction FROM user_info WHERE skill LIKE '%畫%' ORDER BY age DESC
        QueryWrapper<UserInfoEntity> queryWrapper3 = new QueryWrapper<>();
        queryWrapper3.lambda().like(UserInfoEntity::getSkill, "畫");
        queryWrapper3.lambda().orderByDesc(UserInfoEntity::getAge);
        List<UserInfoEntity> userInfoEntityList3 = userInfoService.list(queryWrapper3);
        result.put("studentAgeSkill", userInfoEntityList3);

        //模糊查詢名字帶有"小"或者年齡大於18的學生
        //等價SQL: SELECT id,name,age,skill,evaluate,fraction FROM user_info WHERE name LIKE '%小%' OR age > 18
        QueryWrapper<UserInfoEntity> queryWrapper4 = new QueryWrapper<>();
        queryWrapper4.lambda().like(UserInfoEntity::getName, "小");
        queryWrapper4.lambda().or().gt(UserInfoEntity::getAge, 18);
        List<UserInfoEntity> userInfoEntityList4 = userInfoService.list(queryWrapper4);
        result.put("studentOr", userInfoEntityList4);

        //查詢評價不爲null的學生,並且分頁
        //等價SQL: SELECT id,name,age,skill,evaluate,fraction FROM user_info WHERE evaluate IS NOT NULL LIMIT 0,5
        IPage<UserInfoEntity> page = new Page<>();
        page.setCurrent(1);
        page.setSize(5);
        QueryWrapper<UserInfoEntity> queryWrapper5 = new QueryWrapper<>();
        queryWrapper5.lambda().isNotNull(UserInfoEntity::getEvaluate);
        page = userInfoService.page(page, queryWrapper5);
        result.put("studentPage", page);

        return result;

    }

    public IPage<UserInfoEntity> getInfoListSQL() {
        //查詢大於60分以上的學生,並且分頁。
        IPage<UserInfoEntity> page = new Page<>();
        page.setCurrent(1);
        page.setPages(5);
        page = userInfoService.selectUserInfoByGtFraction(page, 60L);
        return page;
    }

}

6.3 MyBatis-Plus 中 自定義SQL Demo

Usage:
項目中引入Mybatis-Plus組件, 將不會對項目現有的 Mybatis 構架產生任何影響,而且Mybatis-Plus支持所有 Mybatis 原生的特性.
由於某些業務邏輯複雜, 我們可能要自己去寫一些比較複雜的SQL語句.

我們舉一個簡單的例子來演示自定義SQL.
示例:查詢大於設置分數的學生(分數爲動態輸入,且有分頁)

6.3.1 構建 xxxMapper.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">

<mapper namespace="com.example.dao.UserInfoDao">
    <!-- 通用查詢映射結果 -->
    <!--<resultMap id="BaseResultMap" type="com.example.entity.UserInfoEntity">
        <result column="id" property="id"/>
        <result column="name" property="name"/>
        <result column="age" property="age"/>
        <result column="skill" property="skill"/>
        <result column="evaluate" property="evaluate"/>
        <result column="fraction" property="fraction"/>
    </resultMap>-->

    <select id="selectUserInfoByGtFraction" resultType="com.example.entity.UserInfoEntity"
            parameterType="long">
        SELECT 
             * 
        FROM user_info 
        WHERE fraction > #{fraction}
    </select>

</mapper>
6.3.2 dao 層中加入方法

詳見:

    /**
     * 查詢大於該分數的學生
     * @Param  page  分頁參數
     * @Param  fraction  分數
     * @Return IPage<UserInfoEntity> 分頁數據
     */
    IPage<UserInfoEntity> selectUserInfoByGtFraction(IPage<UserInfoEntity> page, @Param("fraction") Long fraction);
6.3.3 service 層中加入方法

詳見:

     /**
     * 查詢大於該分數的學生
     * @Param  page  分頁參數
     * @Param  fraction  分數
     * @Return IPage<UserInfoEntity> 分頁數據
     */
    IPage<UserInfoEntity> selectUserInfoByGtFraction(IPage<UserInfoEntity> page, Long fraction);
6.3.4 serviceImpl 層中加入方法

詳見:

    /**
     * 查詢大於該分數的學生
     * @Param  page  分頁參數
     * @Param  fraction  分數
     * @Return IPage<UserInfoEntity> 分頁數據
     */
    @Override
    public IPage<UserInfoEntity> selectUserInfoByGtFraction(IPage<UserInfoEntity> page, Long fraction) {
        return this.baseMapper.selectUserInfoByGtFraction(page, fraction);
    }
6.3.5 Controller中進行測試

詳見:

package com.example.controller;

import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.baomidou.mybatisplus.core.metadata.IPage;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.example.entity.UserInfoEntity;
import com.example.service.UserInfoService;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;

import java.util.HashMap;
import java.util.List;
import java.util.Map;

/**
 * User: Administrator
 * Date: 2020/4/7
 * Time: 19:14
 * Desc:
 */
@RestController
@RequestMapping("/userInfoPlus")
public class UserInfoPlusController {

    @Autowired
    private UserInfoService userInfoService;

    /**
     * MyBatis-Plus自定義SQL
     * @Return IPage<UserInfoEntity> 分頁數據
     */
    @RequestMapping("/getInfoListSQL")
    public IPage<UserInfoEntity> getInfoListSQL() {
        //查詢大於60分以上的學生,並且分頁。
        IPage<UserInfoEntity> page = new Page<>();
        page.setCurrent(1);
        page.setPages(5);
        page = userInfoService.selectUserInfoByGtFraction(page, 60L);
        return page;
    }

}

三. Postman測試

Postman調用接口效果如下:
在這裏插入圖片描述

四. Swagger2 在線文檔

地址 : http://localhost:8080/swagger-ui.html
在這裏插入圖片描述

五 代碼生成器(AutoGenerator)

5.1 說明

AutoGenerator 是 MyBatis-Plus 的代碼生成器,通過 AutoGenerator 可以快速生成 Entity、Mapper、Mapper XML、Service、Controller 等各個模塊的代碼,極大的提升了開發效率。

特別說明:

自定義模板有哪些可用參數?Github Gitee AbstractTemplateEngine 類中方法 getObjectMap 返回 objectMap 的所有值都可用。

5.2 pom.xml 改造

1. 爲避免generator包衝突, 需把mybatis-plus-boot-starter 包中關聯的generator包給移除掉, 再重新在mybatis-plus-boot-starter 平級包中重新導入;
2. 代碼生成器, 底層使用了 Freemarker 或 Velocity 等模板自動化生成引擎, 故需將其包添加進來;

<!-- mybatisPlus 核心庫 -->
		<dependency>
			<groupId>com.baomidou</groupId>
			<artifactId>mybatis-plus-boot-starter</artifactId>
			<version>3.1.0</version>
			<exclusions>
				<exclusion>
					<groupId>com.baomidou</groupId>
					<artifactId>mybatis-plus-generator</artifactId>
				</exclusion>
			</exclusions>
		</dependency>
		
		<dependency>
			<groupId>com.baomidou</groupId>
			<artifactId>mybatis-plus-generator</artifactId>
			<version>3.1.0</version>
		</dependency>
		
		<!-- mybatisPlus 關聯的模板引擎&文本生成輸出框架(如生成XML,JSP,JAVA等) freemarker-->
		<dependency>
			<groupId>org.freemarker</groupId>
			<artifactId>freemarker</artifactId>
			<version>2.3.30</version>
		</dependency>
		
		<!-- mybatisPlus 關聯的模板引擎&文本生成輸出框架(如生成XML,JSP,JAVA等) velocity-->
		<dependency>
			<groupId>org.apache.velocity</groupId>
			<artifactId>velocity-engine-core</artifactId>
			<version>2.0</version>
		</dependency>

5.3 代碼生成器演示例子

執行 main 方法控制檯輸入模塊表名回車自動生成對應項目目錄中

package com.example.util.generator;


import com.baomidou.mybatisplus.core.exceptions.MybatisPlusException;
import com.baomidou.mybatisplus.core.toolkit.StringPool;
import com.baomidou.mybatisplus.core.toolkit.StringUtils;
import com.baomidou.mybatisplus.generator.AutoGenerator;
import com.baomidou.mybatisplus.generator.InjectionConfig;
import com.baomidou.mybatisplus.generator.config.*;
import com.baomidou.mybatisplus.generator.config.po.TableInfo;
import com.baomidou.mybatisplus.generator.config.rules.NamingStrategy;
import com.baomidou.mybatisplus.generator.engine.FreemarkerTemplateEngine;

import java.util.ArrayList;
import java.util.List;
import java.util.Scanner;

/**
 * User: Administrator
 * Date: 2020/4/9
 * Time: 18:39
 * Desc: 演示例子,執行 main 方法控制檯輸入模塊表名回車自動生成對應項目目錄中
 */
public class CodeGenerator {


    private static String scanner(String tip) {
        Scanner scanner = new Scanner(System.in);
        StringBuilder help = new StringBuilder();
        help.append("請輸入" + tip + ": ");
        System.out.println(help.toString());
        while (scanner.hasNext()) {
            String ipt = scanner.next();
            if (StringUtils.isNotEmpty(ipt)) {
                return ipt;
            }
        }
        throw new MybatisPlusException("請輸入正確的" + tip + "!");
    }

    public static void main(String[] args) {
        // 代碼生成器
        AutoGenerator mpg = new AutoGenerator();

        // 全局配置
        GlobalConfig gc = new GlobalConfig();
        String projectPath = System.getProperty("user.dir");
        gc.setOutputDir(projectPath + "/src/main/java");
        gc.setAuthor("jobob");
        gc.setOpen(false);
        gc.setSwagger2(true); //實體屬性 Swagger2 註解
        mpg.setGlobalConfig(gc);

        // 數據源配置
        DataSourceConfig dsc = new DataSourceConfig();
        dsc.setUrl("jdbc:mysql://{DBMS_IP}:{DBMS_PORT}/user?useUnicode=true&useSSL=false&characterEncoding=utf8");
//         dsc.setSchemaName("user");
        dsc.setDriverName("com.mysql.cj.jdbc.Driver");
        dsc.setUsername("XXXX");
        dsc.setPassword("XXXX");
        mpg.setDataSource(dsc);

        // 包配置
        PackageConfig pc = new PackageConfig();
        pc.setModuleName(scanner("模塊名"));
        pc.setParent("com.baomidou.generatorPKG");
        mpg.setPackageInfo(pc);

        //自定義配置
        InjectionConfig cfg = new InjectionConfig() {
            @Override
            public void initMap() {
                // to do nothing
            }
        };

        // 如果模板是freemarker
        String templatePath = "/templates/mapper.xml.ftl";
        // 如果模板是velocity
//        String templatePath = "/templates/mapper.xml.vm";

        // 自定義輸出配置
        List<FileOutConfig> focList = new ArrayList<>();
        focList.add(new FileOutConfig(templatePath) {
            @Override
            public String outputFile(TableInfo tableInfo) {

                System.out.println(">>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>" + projectPath + "/src/main/resources/mapper/" + pc.getModuleName()
                        + "/" + tableInfo.getEntityName() + "Mapper" + StringPool.DOT_XML);
                // >>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>D:\IdeaProjects-6\springboot_mybatisplus/src/main/resources/mapper/user/InfoMapper.xml

                return projectPath + "/src/main/resources/mapper/" + pc.getModuleName()
                        + "/" + tableInfo.getEntityName() + "Mapper" + StringPool.DOT_XML;
            }
        });

        /*
        cfg.setFileCreate(new IFileCreate() {
            @Override
            public boolean isCreate(ConfigBuilder configBuilder, FileType fileType, String filePath) {
                // 判斷自定義文件夾是否需要創建
                checkDir("調用默認方法創建的目錄");
                return false;
            }
        });
        */

        cfg.setFileOutConfigList(focList);
        mpg.setCfg(cfg);

        //配置模板
        TemplateConfig templateConfig = new TemplateConfig();

        // 配置自定義輸出模板
        //指定自定義模板路徑,注意不要帶上.ftl/.vm, 會根據使用的模板引擎自動識別
        // templateConfig.setEntity("templates/entity2.java");
        // templateConfig.setService();
        // templateConfig.setController();

        templateConfig.setXml(null);
        mpg.setTemplate(templateConfig);

        //策略配置
        StrategyConfig strategy = new StrategyConfig();
        strategy.setNaming(NamingStrategy.underline_to_camel);
        strategy.setColumnNaming(NamingStrategy.underline_to_camel);
//        strategy.setSuperEntityClass("你自己的父類實體, 沒有就不用設置");
        strategy.setEntityLombokModel(true);
        strategy.setRestControllerStyle(true);
        // 公共父類
//        strategy.setSuperControllerClass("你自己的父類控制器, 沒有就不用設置");
        // 寫於父類的公共字段
        strategy.setSuperEntityColumns("id");
        strategy.setInclude(scanner("表名, 多個英文逗號分割").split(","));
        strategy.setControllerMappingHyphenStyle(true);
        strategy.setTablePrefix(pc.getModuleName() + "_");
        mpg.setStrategy(strategy);
        mpg.setTemplateEngine(new FreemarkerTemplateEngine());
        mpg.execute();

    }

}

演示效果圖:
在這裏插入圖片描述

參考列表:
-SpringBoot 整合MyBatis-Plus3.1詳細教程
-MyBatis-Plus 官方文檔
-代碼生成器
-解決org.apache.ibatis.binding.BindingException: Invalid bound statement (not found)問題
-springMVC中的controller層
-FreeMarker使用 & 與spring4集成

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章