最近正在集成SpringBoot與MyBatis-plus, MyBatis-Plus-Join體驗感很好啊

来源:https://www.cnblogs.com/fcloud/archive/2023/09/28/17734798.html
-Advertisement-
Play Games

基本介紹 MyBatis-Plus (opens new window)(簡稱 MP)是一個 MyBatis (opens new window)的增強工具,在 MyBatis 的基礎上只做增強不做改變,為簡化開發、提高效率而生。 MyBatis-Plus特性 無侵入:只做增強不做改變,引入它不會對 ...


基本介紹

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

MyBatis-Plus特性

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

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

MyBatis-Plus-Join特性

無侵入:只做增強不做改變,引入它不會對現有工程產生影響,如絲般順滑
無感引入, 支持MP風格的查詢, 您會MP就會MPJ, 無需額外的學習成本
相容MP的別名、邏輯刪除、枚舉列、TypeHandle列等特性
支持註解形式一對一、一對多和連表查詢形式的一對一和一對多

前置知識

分層領域模型規約

VO 是 Value Object 的縮寫,用於表示一個與前端進行交互的 java 對象。有的朋友也許有疑問,這裡可不可以使用 PO 傳遞數據?實際上,這裡的 VO 只包含前端需要展示的數據即可,對於前端不需要的數據,比如數據創建和修改的時間等欄位,出於減少傳輸數據量大小和保護資料庫結構不外泄的目的,不應該在 VO 中體現出來。通常遵守 Java Bean 的規範,擁有 getter/setter 方法。

DTO 是 Data Transfer Object 的縮寫,用於表示一個數據傳輸對象。DTO 通常用於不同服務或服務不同分層之間的數據傳輸。DTO 與 VO 概念相似,並且通常情況下欄位也基本一致。但 DTO 與 VO 又有一些不同,這個不同主要是設計理念上的,比如 API 服務需要使用的 DTO 就可能與 VO 存在差異。通常遵守 Java Bean 的規範,擁有 getter/setter 方法。

BO 是 Business Object 的縮寫,用於表示一個業務對象。BO 包括了業務邏輯,常常封裝了對 DAO、RPC 等的調用,可以進行 PO 與 VO/DTO 之間的轉換。BO 通常位於業務層,要區別於直接對外提供服務的服務層:BO 提供了基本業務單元的基本業務操作,在設計上屬於被服務層業務流程調用的對象,一個業務流程可能需要調用多個 BO 來完成。

PO 是 Persistant Object 的縮寫,用於表示資料庫中的一條記錄映射成的 java 對象。PO 僅僅用於表示數據,沒有任何數據操作。通常遵守 Java Bean 的規範,擁有 getter/setter 方法。

DAO 是 Data Access Object 的縮寫,用於表示一個數據訪問對象。使用 DAO 訪問資料庫,包括插入、更新、刪除、查詢等操作,與 PO 一起使用。DAO 一般在持久層,完全封裝資料庫操作,對外暴露的方法使得上層應用不需要關註資料庫相關的任何信息。

舉個慄子1

資料庫表:表中的博客包括編號、博客標題、博客內容、博客標簽、博客分類、博客狀態、創建時間、修改時間等。

VO:在客戶端瀏覽器展示的頁面數據,博客標題、博客內容、博客標簽、博客分類、創建時間、上一篇博客URL、下一篇博客URL。

DTO:在服務端數據傳輸的對象,編號、博客標題、博客內容、博客標簽、博客分類、創建時間、上一篇博客編號、下一篇博客編號。

BO:基本業務操作,如管理分類、管理標簽、修改博客狀態等,是我們常說的service層操作。

PO(Entity):包括編號、博客標題、博客內容、博客標簽、博客分類、博客狀態、創建時間、修改時間等。(與資料庫表中的欄位一樣。)

DAO:資料庫增刪改查的方法,例如新增博客、刪除博客、查詢所有博客、更新博客。

舉個慄子2

image

絲滑使用開始了

sql

CREATE TABLE `class` (
  `id` int(11) NOT NULL AUTO_INCREMENT COMMENT '編號',
  `name` varchar(30) DEFAULT NULL COMMENT '班級名',
  `floor` int(3) DEFAULT NULL COMMENT '樓層',
  `teacher_id` int(11) DEFAULT NULL COMMENT '老師編號(FK)',
  PRIMARY KEY (`id`)
) ENGINE=InnoDB AUTO_INCREMENT=30 DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_general_ci COMMENT='班級信息表';
INSERT INTO `class` VALUES ('1', '1年級2班', '4', '2');
INSERT INTO `class` VALUES ('2', '1年級3班', '4', '2');
INSERT INTO `class` VALUES ('3', '2年級1班', '1', '4');
INSERT INTO `class` VALUES ('4', '2年級2班', '2', '5');
INSERT INTO `class` VALUES ('5', '2年級3班', '3', '6');
INSERT INTO `class` VALUES ('6', '3年級1班', '4', '7');
INSERT INTO `class` VALUES ('7', '3年級2班', '1', '8');
INSERT INTO `class` VALUES ('8', '3年級3班', '2', '9');
INSERT INTO `class` VALUES ('9', '4年級1班', '3', '10');
INSERT INTO `class` VALUES ('10', '4年級2班', '4', '11');
INSERT INTO `class` VALUES ('11', '4年級3班', '1', '12');
INSERT INTO `class` VALUES ('12', '5年級1班', '2', '13');
INSERT INTO `class` VALUES ('13', '5年級3班', '4', '15');
INSERT INTO `class` VALUES ('14', '6年級2班', '2', '17');
INSERT INTO `class` VALUES ('15', '6年級3班', '3', '18');
INSERT INTO `class` VALUES ('16', '1年級4班', '4', '99');
INSERT INTO `class` VALUES ('17', '2年級4班', '2', '99');
INSERT INTO `class` VALUES ('18', '3年級4班', '1', '99');
INSERT INTO `class` VALUES ('19', '4年級1班', '1', '20');
INSERT INTO `class` VALUES ('30', '4年級1班', '22', '20');

CREATE TABLE `teacher` (
  `id` int(11) NOT NULL AUTO_INCREMENT COMMENT '編號',
  `name` varchar(30) DEFAULT NULL COMMENT '名字',
  `age` int(2) DEFAULT NULL COMMENT '年齡',
  `title` varchar(30) DEFAULT NULL COMMENT '職稱',
  `manager` int(11) DEFAULT NULL COMMENT '上司編號(FK)',
  `salary` int(6) DEFAULT NULL COMMENT '工資',
  `comm` int(6) DEFAULT NULL COMMENT '獎金',
  `gender` char(1) DEFAULT NULL COMMENT '性別',
  `subject_id` int(11) DEFAULT NULL COMMENT '科目編號(FK)',
  PRIMARY KEY (`id`)
) ENGINE=InnoDB AUTO_INCREMENT=21 DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_general_ci COMMENT='老師信息表';
INSERT INTO `teacher` VALUES ('1', '劉蒼松', '55', '總監', '20', '10000', '5000', '男', '1');
INSERT INTO `teacher` VALUES ('2', '範傳奇', '33', '三級講師', '1', '3000', null, '男', '2');
INSERT INTO `teacher` VALUES ('3', '王克晶', '32', '一級講師', '1', '8000', '3000', '女', '3');
INSERT INTO `teacher` VALUES ('4', '劉國斌', '29', '二級講師', '1', '7300', '3400', '男', '4');
INSERT INTO `teacher` VALUES ('5', '成恆', '35', '三級講師', '1', '5200', '4600', '男', '5');
INSERT INTO `teacher` VALUES ('6', '張皓嵐', '33', '二級講師', '1', '7800', '700', '男', '2');
INSERT INTO `teacher` VALUES ('7', '胡悅', '25', '一級講師', '1', '9000', '2800', '女', '1');
INSERT INTO `teacher` VALUES ('8', '齊雷', '45', '總監', '20', '9800', '7800', '男', '3');
INSERT INTO `teacher` VALUES ('9', '王海濤', '44', '二級講師', '8', '3100', '1200', '男', '4');
INSERT INTO `teacher` VALUES ('10', '張久軍', '39', '一級講師', '8', '2000', '6000', '男', '5');
INSERT INTO `teacher` VALUES ('11', '於健', '27', '二級講師', '12', '3800', null, '男', '2');
INSERT INTO `teacher` VALUES ('12', '張立志', '34', '總監', '20', '13000', '900', '男', '3');
INSERT INTO `teacher` VALUES ('13', '吳華', '46', '總監', '20', '8700', '6900', '男', '5');
INSERT INTO `teacher` VALUES ('14', '李大帥', '29', '三級講師', '13', '7000', null, '男', '1');
INSERT INTO `teacher` VALUES ('15', '田浩', '26', '二級講師', '13', '5600', '1900', '男', '4');
INSERT INTO `teacher` VALUES ('16', '肖旭偉', '36', '一級講師', '12', '6800', '600', '男', '2');
INSERT INTO `teacher` VALUES ('17', '張敏', '29', '三級講師', '13', '6100', '400', '女', '3');
INSERT INTO `teacher` VALUES ('18', '趙微', '26', '二級講師', '13', '4600', '6500', '女', '4');
INSERT INTO `teacher` VALUES ('19', '李源', '25', '三級講師', '13', '6300', '0', '男', '4');
INSERT INTO `teacher` VALUES ('20', '韓少雲', '55', '老闆', null, '1', '0', '男', null);

pom.xml

        <dependency>
            <groupId>mysql</groupId>
            <artifactId>mysql-connector-java</artifactId>
            <version>8.0.28</version>
        </dependency>
		<dependency>
            <groupId>com.alibaba</groupId>
            <artifactId>druid</artifactId>
            <version>1.2.8</version>
        </dependency>
		<dependency>
            <groupId>org.projectlombok</groupId>
            <artifactId>lombok</artifactId>
            <version>1.18.24</version>
        </dependency>
		<dependency>
            <groupId>com.baomidou</groupId>
            <artifactId>mybatis-plus-boot-starter</artifactId>
            <version>3.5.3</version>
        </dependency>
        <dependency>
            <groupId>com.github.yulichang</groupId>
            <artifactId>mybatis-plus-join-boot-starter</artifactId>
            <version>1.4.6</version>
       </dependency>

application.yml

spring:
  # 資料庫連接配置
  datasource:
    driver-class-name: com.mysql.cj.jdbc.Driver
    type: com.alibaba.druid.pool.DruidDataSource
    url: jdbc:mysql://localhost:3306/hedu?useSSL=false&serverTimeZone=Asia/Shanghai
    username: root
    password: root
# mybatis-plus配置
mybatis-plus:
  mapper-locations: classpath:mappers/*.xml
  configuration:
    log-impl: org.apache.ibatis.logging.stdout.StdOutImpl

Mybatis-plus的分頁插件的配置

package cn.highedu.boot.config;

import com.baomidou.mybatisplus.annotation.DbType;
import com.baomidou.mybatisplus.extension.plugins.MybatisPlusInterceptor;
import com.baomidou.mybatisplus.extension.plugins.inner.PaginationInnerInterceptor;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;

@Configuration
public class MybatisPlusConfig {
    /**
     * 分頁插件的配置
     * @return
     */
    @Bean
    public MybatisPlusInterceptor paginationInterceptor(){
        MybatisPlusInterceptor interceptor = new MybatisPlusInterceptor();
        /**
         * DbType.XXX
         * XXX 為具體的資料庫類型如MYSQL,ORACLE
         */
        interceptor.addInnerInterceptor(new PaginationInnerInterceptor(DbType.MYSQL));
        return interceptor;
    }
}

image

創建基本類

Class

package cn.highedu.boot.entity;

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

@Data
@AllArgsConstructor
@NoArgsConstructor
public class Class {
    @TableId(type = IdType.AUTO)
    private Integer id;
    private String name;
    private Integer floor;
    private Integer teacherId;
}

ClassMapper

package cn.highedu.boot.mapper;

import cn.highedu.boot.entity.Class;
import com.baomidou.mybatisplus.core.mapper.BaseMapper;
import com.github.yulichang.base.MPJBaseMapper;
import org.apache.ibatis.annotations.*;

@Mapper
public interface ClassMapper extends BaseMapper<Class>, MPJBaseMapper<Class> {
}

ClassService

package cn.highedu.boot.service;

import cn.highedu.boot.pojo.entity.Class;
import com.github.yulichang.extension.mapping.base.MPJDeepService;

public interface ClassService extends MPJDeepService<Class> {
}

ClassServiceImpl

package cn.highedu.boot.service.impl;

import cn.highedu.boot.entity.Class;
import cn.highedu.boot.mapper.ClassMapper;
import cn.highedu.boot.service.ClassService;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import org.springframework.stereotype.Service;

@Service
public class ClassServiceImpl extends ServiceImpl<ClassMapper, Class> implements ClassService {
}

Teacher

package cn.highedu.boot.entity;

import lombok.AllArgsConstructor;
import lombok.Data;
import lombok.NoArgsConstructor;

@Data
@AllArgsConstructor
@NoArgsConstructor
public class Teacher {
    private Integer id;
    private String name;
    private Integer age;
    private String title;
    private Integer manager;
    private Integer salary;
    private Integer comm;
    private Character gender;
    private Integer subjectId;
}

TeacherMapper

package cn.highedu.boot.mapper;

import cn.highedu.boot.entity.Teacher;
import com.baomidou.mybatisplus.core.mapper.BaseMapper;
import com.github.yulichang.base.MPJBaseMapper;
import org.apache.ibatis.annotations.*;

@Mapper
public interface TeacherMapper extends BaseMapper<Teacher>, MPJBaseMapper<Teacher> {
}

TeacherService

package cn.highedu.boot.service;

import cn.highedu.boot.pojo.entity.Teacher;
import com.github.yulichang.extension.mapping.base.MPJDeepService;

public interface TeacherService extends MPJDeepService<Teacher> {
}

TeacherServiceImpl

package cn.highedu.boot.service.impl;

import cn.highedu.boot.entity.Teacher;
import cn.highedu.boot.mapper.TeacherMapper;
import cn.highedu.boot.service.TeacherService;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import org.springframework.stereotype.Service;

@Service
public class TeacherServiceImpl extends ServiceImpl<TeacherMapper, Teacher> implements TeacherService {
}

TeacherVO

package cn.highedu.boot.pojo.vo;

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

@Data
@AllArgsConstructor
@NoArgsConstructor
public class TeacherVO {
    @TableId(type = IdType.AUTO)
    private Integer id;
    private String name;
    private Integer age;
    private String title;
    private Integer manager;
    private Integer salary;
    private Integer comm;
    private Character gender;
    private Integer subjectId;

    private String  className;
    private Integer floor;
}

單表操作

SingleTableOperationTest

package cn.highedu.boot.service;

import cn.highedu.boot.entity.Class;
import cn.highedu.boot.mapper.ClassMapper;
import cn.highedu.boot.service.impl.ClassServiceImpl;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.core.toolkit.Wrappers;
import org.junit.jupiter.api.Test;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.test.context.SpringBootTest;

import java.util.List;

@SpringBootTest
class ClassServiceTest  extends ClassServiceImpl {

    @Autowired
    private ClassMapper classMapperSimple;

    //基本操作
    //insert
    /**
     * 新增一條記錄
     */
    @Test
    void simpleAddOne(){
        Class addOneClazz = new Class();
        addOneClazz.setName("4年級1班");
        addOneClazz.setFloor(22);
        addOneClazz.setTeacherId(20);
        //INSERT INTO class ( name, floor, teacher_id ) VALUES ( ?, ?, ? );
        int addOneResult = classMapperSimple.insert(addOneClazz);
        System.out.println(addOneResult);
    }

    //delete
    /**
     * 根據Id刪除一條記錄
     */
    @Test
    void simpleDeleteOneById(){
        //DELETE FROM class WHERE id=?;
        int deleteByIdResult = classMapperSimple.deleteById(1);
        System.out.println(deleteByIdResult);
    }

    //update
    /**
     * 根據Id更改一條記錄
     */
    @Test
    void simpleUpdateOneById(){
        Class updateClass = new Class();
        updateClass.setId(2);
        updateClass.setName("1年級3班");
        updateClass.setFloor(4);
        updateClass.setTeacherId(2);
        //UPDATE class SET name=?, floor=?, teacher_id=? WHERE id=?;
        int updateByIdResult = classMapperSimple.updateById(updateClass);
        System.out.println(updateByIdResult);
    }

    //select
    /**
     * 根據Id查詢一條記錄
     */
    @Test
    void simpleQueryOneById(){
        //SELECT id,name,floor,teacher_id FROM class WHERE id=?;
        Class queryOneClass = classMapperSimple.selectById(1);
        System.out.println(queryOneClass);
    }


    /**
     * 查詢所有記錄
     */
    @Test
    void simpleQueryAll() {
        //SELECT id,name,floor,teacher_id FROM class;
        List<Class> queryClasses = classMapperSimple.selectList(null);
        System.out.println(queryClasses);
    }


    /**
     *|     函數名   |     說明     |
     *| ----------- | -----------  |
     *|      eq     |     等於     |
     *|      ne     |     不等     |
     *|      gt     |     大於     |
     *|      it     |     小於     |
     *|    between  | 在值1到值2之間 |
     *|     like    |   模糊查詢    |
     *|     isNull  |  欄位為NULL   |
     */

    @Autowired
    private ClassMapper classMapperComplex;

    //進階操作

    //單表操作
    //select
    /**
     * 根據Id查詢1條數據
     */
    @Test
    void complexQueryOne(){
        LambdaQueryWrapper<Class> queryWrapper = Wrappers.lambdaQuery();
        queryWrapper.eq(Class::getId, 1);
        //SELECT id,name,floor,teacher_id FROM class WHERE (id = ?);
        Class complexQueryOne = classMapperComplex.selectOne(queryWrapper);
        System.out.println(complexQueryOne);
    }
    /**
     * 查詢相同條件的數據
     */
    @Test
    void complexQueryAll(){
        LambdaQueryWrapper<Class> queryWrapper = Wrappers.lambdaQuery();
        queryWrapper.eq(Class::getFloor,1);
        //SELECT id,name,floor,teacher_id FROM class WHERE (floor = ?);
        List<Class> complexQueryAll = classMapperComplex.selectList(queryWrapper);
        System.out.println(complexQueryAll);
    }


    /**
     * 查詢範圍內的數據
     */
    @Test
    void complexBetweenQuery(){
        LambdaQueryWrapper<Class> queryWrapper = Wrappers.lambdaQuery();
        queryWrapper.between(Class::getFloor,1,3);
        //SELECT id,name,floor,teacher_id FROM class WHERE (floor BETWEEN ? AND ?);
        List<Class> complexQueryAll = classMapperComplex.selectList(queryWrapper);
        System.out.println(complexQueryAll);
    }

    /**
     * 模糊查詢
     * like():前後加百分號,如 %1年級%
     * likeLeft():前面加百分號,如 %1年級
     * likeRight():後面加百分號,如 1年級%
     */
    @Test
    void complexLikeQuery(){
        LambdaQueryWrapper<Class> queryWrapper = Wrappers.lambdaQuery();
        queryWrapper.likeRight(Class::getName,"1年級");
        // SELECT id,name,floor,teacher_id FROM class WHERE (name LIKE ?);
        List<Class> complexLikeQuery = classMapperComplex.selectList(queryWrapper);
        System.out.println(complexLikeQuery);
    }

    /**
     * 按照樓層升序排列,從小到大
     */
    @Test
    void complexOrderQuery(){
        LambdaQueryWrapper<Class> queryWrapper = Wrappers.lambdaQuery();
        //condition :條件,返回boolean,當condition為true,進行排序,如果為false,則不排序
        //isAsc:是否為升序,true為升序,false為降序
        //columns:需要操作的列
        queryWrapper.orderBy(true,true,Class::getFloor);
        //SELECT id,teacher_id,name,floor FROM class ORDER BY floor ASC;
        List<Class> complexOrderByAscQuery= classMapperComplex.selectList(queryWrapper);
        System.out.println(complexOrderByAscQuery);
    }
    /**
     * 分頁非條件查詢,查詢第1頁,3條數據
     */
    @Test
    void complexPageQuery(){
        Page<Class> page = new Page<>(1,3);
        //SELECT id,teacher_id,name,floor FROM class LIMIT ?;
        classMapperComplex.selectPage(page, null);
        System.out.println(page.getRecords());//每頁數據list集合

        System.out.println(page.getCurrent());//當前頁
        System.out.println(page.getSize());//每頁顯示記錄數
        System.out.println(page.getTotal());//總記錄數
        System.out.println(page.getPages());//總頁數

        System.out.println(page.hasPrevious());//上一頁
        System.out.println(page.hasNext());//下一頁
    }

    /**
     * 分頁條件查詢,查詢1到3樓的班級信息,顯示第1頁,3條數據
     */
    @Test
    void complexPageQueryWrapper(){
        LambdaQueryWrapper<Class> queryWrapper = Wrappers.lambdaQuery();
        Page<Class> page = new Page<>(1,3);
        //SELECT id,teacher_id,name,floor FROM class WHERE (floor BETWEEN ? AND ?) LIMIT ?;
        classMapperComplex.selectPage(page, queryWrapper.between(Class::getFloor,1,3));
    }
}

多表操作

MultipleTableOperationTest

package cn.highedu.boot.service;

import cn.highedu.boot.pojo.vo.TeacherVO;
import cn.highedu.boot.pojo.entity.Class;
import cn.highedu.boot.pojo.entity.Teacher;
import cn.highedu.boot.mapper.TeacherMapper;
import cn.highedu.boot.service.impl.TeacherServiceImpl;
import com.baomidou.mybatisplus.core.metadata.IPage;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.github.yulichang.wrapper.MPJLambdaWrapper;
import org.junit.jupiter.api.Test;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.test.context.SpringBootTest;

import java.util.List;

@SpringBootTest
public class MultipleTableOperationTest extends TeacherServiceImpl {

    @Autowired
    private TeacherMapper teacherMapper;

    /**
     * 查詢樓層大於2的所有老師及各個老師所在的班級信息,並按樓層的升序排列
     */
    @Test
    void selectTeachersWhichOverFloor(){
        MPJLambdaWrapper<Teacher> wrapper = new MPJLambdaWrapper<Teacher>();
        wrapper.selectAll(Teacher.class)//查詢Teacher表全部欄位
                .select(Class::getFloor, Class::getName)
                .rightJoin(Class.class, Class::getTeacherId, Teacher::getId)
                .gt(Class::getFloor,1)
                .orderByAsc(Class::getFloor);
        /* SELECT
         *      t.id,t.name,t.age,t.title,t.manager,t.salary,t.comm,t.gender,
         *      t.subject_id,t1.floor,t1.name
         * FROM
         *      teacher t
         * RIGHT JOIN
         *      class t1
         * ON
         *      (t1.teacher_id = t.id);
         * WHERE
         *      (t1.floor > ?)
         * ORDER BY
         *      t1.floor ASC
         */
        List<TeacherVO> teacherList = teacherMapper.selectJoinList(TeacherVO.class, wrapper);
        System.out.println(teacherList);
    }

    /**
     * 在上面的基礎上,增添了分頁的功能,查詢第2頁,每頁5條數據
     */
    @Test
    void selectTeachersWhichOverFloorPage(){
        MPJLambdaWrapper<Teacher> wrapper = new MPJLambdaWrapper<Teacher>();
        wrapper.selectAll(Teacher.class)//查詢Teacher表全部欄位
                .select(Class::getFloor, Class::getName)
                .rightJoin(Class.class, Class::getTeacherId, Teacher::getId)
                .gt(Class::getFloor,1)
                .orderByAsc(Class::getFloor);
        Page<TeacherVO> page = new Page<>(2, 5);
        /* SELECT
         *      t.id,t.name,t.age,t.title,t.manager,t.salary,t.comm,t.gender,
         *      t.subject_id,t1.floor,t1.name
         * FROM
         *      teacher t
         * RIGHT JOIN
         *      class t1
         * ON
         *      (t1.teacher_id = t.id);
         * WHERE
         *      (t1.floor > ?)
         * ORDER BY
         *      t1.floor ASC
         * LIMIT
         *      ?,?
         */
        IPage<TeacherVO> teacherList = teacherMapper.selectJoinPage(page, TeacherVO.class,wrapper);
        System.out.println(teacherList);
    }
}

參考

Java版本為17
項目的藍奏雲: https://robotboy.lanzoue.com/i1szr1a5s1hi

MyBatis-Plus-Join官網--------------MyBatis-Plus官網
https://blog.csdn.net/qq_52880445/article/details/124632069
https://zhuanlan.zhihu.com/p/102389552


您的分享是我們最大的動力!

-Advertisement-
Play Games
更多相關文章
  • 目錄場景1 定義全部異常處理類2 替換request引用3 代碼優化總結 場景 本文前端用的是阿裡的Ant-Design框架,其他框架也有全局攔截器,思路是相同,具體實現自行百度下吧 因為每次都需要調介面,都需要單獨處理異常情況(code !=0),因此前端需要對後端返回的通用響應進行統一處理,比如 ...
  • 在Dart學習的第02天,我們通過基礎語法說明和樣例代碼的方式,學習了Dart的16個基礎語法,這些基礎語法給我們後面編寫的Flutter程式打下來堅實基礎。今天,我們繼續深入學習Dart乃至所有編程語言都非常重要的部分:可迭代的集合…… ...
  • 本篇博文圍繞使用Python開發熱門游戲2048 GAME(命令行版本) 代碼未做任何優化(原生且隨意)、全程以面向過程、MVC的設計思想為主、開發環境是Ubuntu系統下的Pycharm 2048是我很久以前學習Python過程中的一個作業,接下來直入正題—— 一、瞭解游戲 1. 介紹 《2048 ...
  • 這是一個FTP(文件傳輸協議)管理工具,能夠支持文件上傳下載以及操作服務端的文件。 該工具由客戶端和服務端組成。客戶端與服務端通過Socket連接實現通信,客戶端發送命令,服務端解析並執行相應的操作。部分代碼已省略,下麵是服務端和客戶端代碼的詳細解釋。 GitHub:https://github.c ...
  • 基於java線上調查問卷系統設計與實現(含配套lun文,ppt),可適用於基於java線上校園調查問卷,基於java校園問卷調查系統,java問卷調查系統,校園線上問卷調查,校園線上調查問卷系統設計,調查問卷管理系統,基於Javaweb實現線上調查問卷系統,網上調查問卷系統,網上問卷調查系統等等; ...
  • 現象 大量的分支選擇型代碼段看著讓人頭疼 for (Field field : declaredFields) { Class<?> type = field.getType(); String key = field.getName(); Element result = resultMap.ad ...
  • 文件目錄結構 tree . ├── bin ├── include │ └── calc.h ├── lib │ ├── add.c │ ├── div.c │ ├── mul.c │ └── sub.c └── src └── main.c 4 directories, 6 files 靜態庫生成 ...
  • 第一題 下列程式輸出啥? public class StringDemo{ private static final String MESSAGE="taobao"; public static void main(String [] args) { String a ="tao"+"bao"; S ...
一周排行
    -Advertisement-
    Play Games
  • 移動開發(一):使用.NET MAUI開發第一個安卓APP 對於工作多年的C#程式員來說,近來想嘗試開發一款安卓APP,考慮了很久最終選擇使用.NET MAUI這個微軟官方的框架來嘗試體驗開發安卓APP,畢竟是使用Visual Studio開發工具,使用起來也比較的順手,結合微軟官方的教程進行了安卓 ...
  • 前言 QuestPDF 是一個開源 .NET 庫,用於生成 PDF 文檔。使用了C# Fluent API方式可簡化開發、減少錯誤並提高工作效率。利用它可以輕鬆生成 PDF 報告、發票、導出文件等。 項目介紹 QuestPDF 是一個革命性的開源 .NET 庫,它徹底改變了我們生成 PDF 文檔的方 ...
  • 項目地址 項目後端地址: https://github.com/ZyPLJ/ZYTteeHole 項目前端頁面地址: ZyPLJ/TreeHoleVue (github.com) https://github.com/ZyPLJ/TreeHoleVue 目前項目測試訪問地址: http://tree ...
  • 話不多說,直接開乾 一.下載 1.官方鏈接下載: https://www.microsoft.com/zh-cn/sql-server/sql-server-downloads 2.在下載目錄中找到下麵這個小的安裝包 SQL2022-SSEI-Dev.exe,運行開始下載SQL server; 二. ...
  • 前言 隨著物聯網(IoT)技術的迅猛發展,MQTT(消息隊列遙測傳輸)協議憑藉其輕量級和高效性,已成為眾多物聯網應用的首選通信標準。 MQTTnet 作為一個高性能的 .NET 開源庫,為 .NET 平臺上的 MQTT 客戶端與伺服器開發提供了強大的支持。 本文將全面介紹 MQTTnet 的核心功能 ...
  • Serilog支持多種接收器用於日誌存儲,增強器用於添加屬性,LogContext管理動態屬性,支持多種輸出格式包括純文本、JSON及ExpressionTemplate。還提供了自定義格式化選項,適用於不同需求。 ...
  • 目錄簡介獲取 HTML 文檔解析 HTML 文檔測試參考文章 簡介 動態內容網站使用 JavaScript 腳本動態檢索和渲染數據,爬取信息時需要模擬瀏覽器行為,否則獲取到的源碼基本是空的。 本文使用的爬取步驟如下: 使用 Selenium 獲取渲染後的 HTML 文檔 使用 HtmlAgility ...
  • 1.前言 什麼是熱更新 游戲或者軟體更新時,無需重新下載客戶端進行安裝,而是在應用程式啟動的情況下,在內部進行資源或者代碼更新 Unity目前常用熱更新解決方案 HybridCLR,Xlua,ILRuntime等 Unity目前常用資源管理解決方案 AssetBundles,Addressable, ...
  • 本文章主要是在C# ASP.NET Core Web API框架實現向手機發送驗證碼簡訊功能。這裡我選擇是一個互億無線簡訊驗證碼平臺,其實像阿裡雲,騰訊雲上面也可以。 首先我們先去 互億無線 https://www.ihuyi.com/api/sms.html 去註冊一個賬號 註冊完成賬號後,它會送 ...
  • 通過以下方式可以高效,並保證數據同步的可靠性 1.API設計 使用RESTful設計,確保API端點明確,並使用適當的HTTP方法(如POST用於創建,PUT用於更新)。 設計清晰的請求和響應模型,以確保客戶端能夠理解預期格式。 2.數據驗證 在伺服器端進行嚴格的數據驗證,確保接收到的數據符合預期格 ...