MyBatis教程[8]----使用MyBatis-Plus簡化開發

前面用了7篇博客,講完了mybatis。掌握了前面7篇博客的內容,便可以自如應對spring下的mybatis開發了。

然而,很多時候Mybatis的表現並不是那麼完美,比如很多簡單的CURD語句還需要開發者手動完成;不支持分頁功能,需要開發者寫代碼實現分頁邏輯等等。。。。

這時候,就不得不提MyBatis-Plus了,MyBatis-Plus正是爲簡化Mybatis的開發而誕生的。

1. MyBatis-Plus介紹

官網關於MyBatis-Plus簡介的第一句話就是:

MyBatis-Plus(簡稱 MP)是一個 MyBatis 的增強工具,在 MyBatis 的基礎上只做增強不做改變,爲簡化開發、提高效率而生。

只做增強,不做改變。這意味着原來寫的MyBatis代碼可以直接拿來用在MyBatis-Plus上,而幾乎不用做任何修改。
在這裏插入圖片描述
就像 魂鬥羅 中的 1P、2P,基友搭配,效率翻倍。

在這裏直接貼上官網對MP的特性介紹:

  • 無侵入:只做增強不做改變,引入它不會對現有工程產生影響,如絲般順滑
  • 損耗小:啓動即會自動注入基本 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 操作智能分析阻斷,也可自定義攔截規則,預防誤操作

本文將演示一下SpringBoot + MyBatis-Plus項目環境的搭建,以及使用MyBatis-Plus內置的CRUD,以及演示分頁。

2. SpringBoot整合MyBatis-Plus

2.1 新建SpringBoot項目

第一步:新創建SpringBoot項目,這一步前面已經做了很多次了,不詳細說了。

新創建好的項目的目錄結構:
在這裏插入圖片描述

2.2 添加依賴

需要添加的依賴有:

  • mysql-connector-java:數據庫驅動
  • lombok:可自動生成Getter、Setter、toString方法
  • mybatis-plus-boot-starter:mybatis-plus啓動器

添加依賴:

<!--mysql驅動-->
<dependency>
    <groupId>mysql</groupId>
    <artifactId>mysql-connector-java</artifactId>
    <scope>runtime</scope>
</dependency>

<!--自動生成Getter、Setter、toString方法的插件-->
<dependency>
    <groupId>org.projectlombok</groupId>
    <artifactId>lombok</artifactId>
</dependency>

<!--mybatis-plus啓動器-->
<dependency>
    <groupId>com.baomidou</groupId>
    <artifactId>mybatis-plus-boot-starter</artifactId>
    <version>3.3.1</version>
</dependency>

2.3 配置數據源以及mybatis-plus

spring:
  datasource:
    username: root
    password: 123
    #mysql8以上的驅動包需要指定以下時區
    url: jdbc:mysql://127.0.0.1:23306/study-mybatis?serverTimezone=GMT%2B8&useUnicode=true&characterEncoding=utf-8
    driver-class-name: com.mysql.cj.jdbc.Driver

mybatis-plus:
  # 指定實體類所有包
  type-aliases-package: com.yky.springboot.entities
  # 指定xml映射配置文件掃描路徑
  mapper-locations: classpath:mapper/*.xml

2.4 創建實體類

在entities包下創建User類,代碼爲下:

package com.yky.springboot.entities;

import com.baomidou.mybatisplus.annotation.IdType;
import com.baomidou.mybatisplus.annotation.TableId;
import lombok.Data;

import java.io.Serializable;
import java.util.Date;

@Data
public class User implements Serializable {
	//指定一下主鍵id
    @TableId(type = IdType.AUTO)
    private Long id;
    private String name;
    private String phone;
    private Date birthday;
}

2.5 創建Mapper接口

package com.yky.springboot.mapper;

import com.baomidou.mybatisplus.core.mapper.BaseMapper;
import com.yky.springboot.entities.User;
import org.apache.ibatis.annotations.Mapper;

@Mapper
public interface UserMapper extends BaseMapper<User> {
}

在這裏,只需要繼承BaseMapper接口,甚至不用寫mapper映射配置文件,便可直接使用MP內部的CRUD操作接口。

MP默認提供了以下操作CRUD接口:

/**
 * 插入一條記錄
 *
 * @param entity 實體對象
 */
int insert(T entity);

/**
 * 根據 ID 刪除
 *
 * @param id 主鍵ID
 */
int deleteById(Serializable id);

/**
 * 根據 columnMap 條件,刪除記錄
 *
 * @param columnMap 表字段 map 對象
 */
int deleteByMap(@Param(Constants.COLUMN_MAP) Map<String, Object> columnMap);

/**
 * 根據 entity 條件,刪除記錄
 *
 * @param wrapper 實體對象封裝操作類(可以爲 null)
 */
int delete(@Param(Constants.WRAPPER) Wrapper<T> wrapper);

/**
 * 刪除(根據ID 批量刪除)
 *
 * @param idList 主鍵ID列表(不能爲 null 以及 empty)
 */
int deleteBatchIds(@Param(Constants.COLLECTION) Collection<? extends Serializable> idList);

/**
 * 根據 ID 修改
 *
 * @param entity 實體對象
 */
int updateById(@Param(Constants.ENTITY) T entity);

/**
 * 根據 whereEntity 條件,更新記錄
 *
 * @param entity        實體對象 (set 條件值,可以爲 null)
 * @param updateWrapper 實體對象封裝操作類(可以爲 null,裏面的 entity 用於生成 where 語句)
 */
int update(@Param(Constants.ENTITY) T entity, @Param(Constants.WRAPPER) Wrapper<T> updateWrapper);

/**
 * 根據 ID 查詢
 *
 * @param id 主鍵ID
 */
T selectById(Serializable id);

/**
 * 查詢(根據ID 批量查詢)
 *
 * @param idList 主鍵ID列表(不能爲 null 以及 empty)
 */
List<T> selectBatchIds(@Param(Constants.COLLECTION) Collection<? extends Serializable> idList);

/**
 * 查詢(根據 columnMap 條件)
 *
 * @param columnMap 表字段 map 對象
 */
List<T> selectByMap(@Param(Constants.COLUMN_MAP) Map<String, Object> columnMap);

/**
 * 根據 entity 條件,查詢一條記錄
 *
 * @param queryWrapper 實體對象封裝操作類(可以爲 null)
 */
T selectOne(@Param(Constants.WRAPPER) Wrapper<T> queryWrapper);

/**
 * 根據 Wrapper 條件,查詢總記錄數
 *
 * @param queryWrapper 實體對象封裝操作類(可以爲 null)
 */
Integer selectCount(@Param(Constants.WRAPPER) Wrapper<T> queryWrapper);

/**
 * 根據 entity 條件,查詢全部記錄
 *
 * @param queryWrapper 實體對象封裝操作類(可以爲 null)
 */
List<T> selectList(@Param(Constants.WRAPPER) Wrapper<T> queryWrapper);

/**
 * 根據 Wrapper 條件,查詢全部記錄
 *
 * @param queryWrapper 實體對象封裝操作類(可以爲 null)
 */
List<Map<String, Object>> selectMaps(@Param(Constants.WRAPPER) Wrapper<T> queryWrapper);

/**
 * 根據 Wrapper 條件,查詢全部記錄
 * <p>注意: 只返回第一個字段的值</p>
 *
 * @param queryWrapper 實體對象封裝操作類(可以爲 null)
 */
List<Object> selectObjs(@Param(Constants.WRAPPER) Wrapper<T> queryWrapper);

/**
 * 根據 entity 條件,查詢全部記錄(並翻頁)
 *
 * @param page         分頁查詢條件(可以爲 RowBounds.DEFAULT)
 * @param queryWrapper 實體對象封裝操作類(可以爲 null)
 */
<E extends IPage<T>> E selectPage(E page, @Param(Constants.WRAPPER) Wrapper<T> queryWrapper);

/**
 * 根據 Wrapper 條件,查詢全部記錄(並翻頁)
 *
 * @param page         分頁查詢條件
 * @param queryWrapper 實體對象封裝操作類
 */
<E extends IPage<Map<String, Object>>> E selectMapsPage(E page, @Param(Constants.WRAPPER) Wrapper<T> queryWrapper);

開發者可直接調用這些接口方法操作數據庫,而無須關心接口的內部實現,大大簡化了開發,提高了開發效率。

2.6 創建Service層

在Web開發中,Controller層調用Service層代碼,業務邏輯寫在Service層;Service層調用Dao層代碼(這裏的Dao層就是Mapper接口),Dao層操作數據庫。所以,一般情況下還需要開發Service層。

Service接口需要這樣寫:

package com.yky.springboot.service;

import com.baomidou.mybatisplus.extension.service.IService;
import com.yky.springboot.entities.User;

public interface UserService extends IService<User> {
}

光有Service接口還不夠,還需要有接口實現:

package com.yky.springboot.service.impl;

import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.yky.springboot.entities.User;
import com.yky.springboot.mapper.UserMapper;
import com.yky.springboot.service.UserService;
import org.springframework.stereotype.Service;

@Service
public class UserServiceImpl extends ServiceImpl<UserMapper, User> implements UserService {
}

只需要繼承ServiceImpl類便可直接調用Mapper接口的方法了,因爲Service層是面向接口編程,所以我們還繼承了前面寫的UserService接口。

至此,Dao層、Service層均已創建好了。

如果想在Service層的實現類中調用Mapper代碼,直接用baseMapper即可(所繼承的ServiceImpl中有注入Mapper進來):
在這裏插入圖片描述

3. 單元測試

@SpringBootTest
class UserServiceTest {

    @Autowired
    UserService userService;

    /**
     * 新增或修改數據(如果主鍵id不爲空,且id已在數據庫中存在了,則進行更新操作)
     */
    @Test
    public void insert() throws ParseException {
        User user = new User();
        user.setName("法外狂徒張三");
        user.setPhone("11111111111");
        user.setBirthday(new SimpleDateFormat("yyyy-MM-dd").parse("1996-07-18"));

        userService.saveOrUpdate(user);
    }

    /**
     * 刪除數據
     */
    @Test
    public void delete() {
        userService.removeById(1);
    }


    /**
     * 獲取所有
     */
    @Test
    public void selectAll() {
        List<User> users = userService.list();

        System.out.println(users);
    }

    /**
     * 根據id獲取
     */
    @Test
    public void getById() {
        User user = userService.getById(1);
        System.out.println(user);
    }

}

至此,我們沒有寫任何的xml映射配置代碼,就已經完成了對數據庫的大部分操作。接下來,我們來完成一下分頁。

4. 分頁查詢

分頁查詢的實現步驟:

  1. 配置分頁插件
  2. 在Mapper接口編寫分頁查詢接口
  3. 編寫SQL語句,查詢數據庫
  4. Service層調用分頁查詢接口

4.1 配置分頁插件

新創建config.MybatisPlusConfig並寫入以下代碼:

package com.yky.springboot.config;

import com.baomidou.mybatisplus.extension.plugins.PaginationInterceptor;
import org.mybatis.spring.annotation.MapperScan;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.transaction.annotation.EnableTransactionManagement;

/**
 * mybatisPlus配置
 */
@EnableTransactionManagement//開啓事務管理
//@MapperScan("com.mengxuegu.web.mapper")//掃描Mapper接口,就不需要在Mapper接口上加Mapper註解了
@Configuration
public class MybatisPlusConfig {

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

4.2 編寫分頁查詢接口

/**
 * 分頁查詢接口
 * @param page 分頁對象
 * @param user 用於查詢的實體對象
 * @return 分頁數據
 */
IPage<User> selectPage(Page<User> page,@Param("user") User user);

Page對象的屬性:

public class Page<T> implements IPage<T> {
/**
     * 查詢數據列表
     */
    private List<T> records = Collections.emptyList();

    /**
     * 總數
     */
    private long total = 0;
    /**
     * 每頁顯示條數,默認 10
     */
    private long size = 10;

    /**
     * 當前頁
     */
    private long current = 1;

    /**
     * 排序字段信息
     */
    private List<OrderItem> orders = new ArrayList<>();

    /**
     * 自動優化 COUNT SQL
     */
    private boolean optimizeCountSql = true;
    /**
     * 是否進行 count 查詢
     */
    private boolean isSearchCount = true;
    /**
     * 是否命中count緩存
     */
    private boolean hitCount = false;
}

我們可以設置page對象的size、current屬性來進行分頁查詢,查詢結果封裝在records中。

4.3 編寫xml映射配置文件

在resources/mapper目錄下創建UserMapper.xml文件,並寫入以下代碼:

<!DOCTYPE mapper
        PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN"
        "http://mybatis.org/dtd/mybatis-3-mapper.dtd">

<!--namespace對應Mapper接口的全類名,這樣就可以自動匹配上-->
<mapper namespace="com.yky.springboot.mapper.UserMapper">
    <select id="selectPage" resultType="User">
        SELECT
            *
        FROM `user`

        <where>
            <if test="user.name != null and user.name != ''">
                name LIKE CONCAT('%',#{user.name},'%')
            </if>

            <if test="user.phone != null and user.phone != ''">
                AND `phone` = #{user.phone}
            </if>
        </where>
    </select>
</mapper>

在這裏,都不需要寫LIMIT語句,MyBatis-Plus會自動幫我們添加上(根據傳入的Page對象,自動生成LIMIT語句)。

4.4 單元測試測試Dao層代碼

@Autowired
UserMapper userMapper;
@Test
public void selectPage() {
    User user = new User();
    user.setName("小");
    IPage<User> userPage = userMapper.selectPage(new Page<User>(),user);

    System.out.println(userPage.getRecords());
}

4.5 編寫Service層分頁查詢代碼

編寫Service接口:

/**
 * 分頁查詢數據
 * @param size 單頁大小
 * @param current 當前頁碼
 * @param user 用於查詢的實體對象
 * @return 分頁數據
 */
IPage<User> selectPage(long size, long current, User user);

編寫接口實現:

    @Override
public IPage<User> selectPage(long size, long current, User user) {
    Page page = new Page();
    page.setSize(size);
    page.setCurrent(current);

    return baseMapper.selectPage(page,user);
}

單元測試Service層代碼

@Test
public void selectPage() {
    User user = new User();
    user.setName("小");
    IPage<User> page = userService.selectPage(3, 1, user);
    System.out.println(page.getRecords());
    System.out.println(page.getTotal());
}

至此,使用MyBatis-Plus進行分頁查詢的功能開發完成,相比於手寫分頁簡單多了。關於使用MyBatis-Plus簡化MyBatis開發就講到這裏了,如果想了解更多可移步MyBatis-Plus官網。如果有什麼問題,歡迎大家在評論區指出。

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