主頁 > 軟體設計 > 一篇文章帶你掌握MyBatis簡化框架——MyBatisPlus

一篇文章帶你掌握MyBatis簡化框架——MyBatisPlus

2022-10-18 07:53:33 軟體設計

一篇文章帶你掌握MyBatis簡化框架——MyBatisPlus

我們在前面的文章中已經學習了目前開發所需的主流框架

類似于我們所學習的SpringBoot框架用于簡化Spring開發,我們的國人大大也開發了一款MyBatisPlus框架用來簡化MyBatis開發

下面讓我們來逐步掌握MyBatisPlus的內容吧~

MyBatisPlus簡介

首先我們來簡單介紹一下MyBatisPlus:

  • MyBatisPlus(MP)是基于MyBatis框架基礎上開發的增強型工具,旨在簡化開發,提高效率

MyBatisPlus開發具有三種開發方式:

  • 基于MyBatis使用MyBatisPlus
  • 基于Spring使用MyBatisPlus
  • 基于SpringBoot使用MyBatisPlus

MyBatisPlus入門案例

我們以基于SpringBoot使用MyBatisPlus為案例來展示MyBatisPlus開發的便捷性

SpringBoot使用MyBatis

首先我們回憶一下SpringBoot使用MyBatis開發的相關步驟:

  1. 創建SpringBoot工程
  2. 勾選配置使用技術
  3. 設定DataSource相關屬性(JDBC引數)
  4. 定義資料層介面映射配置

其中最為繁瑣的就是資料層介面的配置,需要書寫大量的@注解來進行資料庫的查詢

package com.itheima.dao;

import com.itheima.domain.Book;
import org.apache.ibatis.annotations.*;

import java.util.List;

@Mapper
public interface BookDao {

    @Insert("insert into tbl_book (type,name,description) values(#{type},#{name},#{description})")
    public int save(Book book);

    @Update("update tbl_book set type = #{type}, name = #{name}, description = #{description} where id = #{id}")
    public int update(Book book);

    @Delete("delete from tbl_book where id = #{id}")
    public int delete(Integer id);

    @Select("select * from tbl_book where id = #{id}")
    public Book getById(Integer id);

    @Select("select * from tbl_book")
    public List<Book> getAll();
}

SpringBoot使用MyBatisPlus

我們的SpringBoot使用MyBatisPlus大量簡化了資料層代碼書寫

我們下面依次介紹整體步驟:

  1. 創建專案(SpringBoot專案,勾選相應技術堆疊)

  1. 匯入相關依賴坐標
<?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.5.0</version>
        <relativePath/> <!-- lookup parent from repository -->
    </parent>
    <groupId>com.itheima</groupId>
    <artifactId>mybatisplus_01_quickstart</artifactId>
    <version>0.0.1-SNAPSHOT</version>
    <properties>
        <java.version>1.8</java.version>
    </properties>
    <dependencies>

        <!--由于SpringBoot中未整合MyBatisPlus,所以我們需要手動添加MyBatisPlus依賴坐標-->
        <dependency>
            <groupId>com.baomidou</groupId>
            <artifactId>mybatis-plus-boot-starter</artifactId>
            <version>3.4.1</version>
        </dependency>

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

        <!--德魯伊坐標-->
        <dependency>
            <groupId>com.alibaba</groupId>
            <artifactId>druid</artifactId>
            <version>1.1.16</version>
        </dependency>

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

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

    </dependencies>

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

</project>
  1. 配置環境yaml
spring:
  datasource:
    type: com.alibaba.druid.pool.DruidDataSource
    driver-class-name: com.mysql.cj.jdbc.Driver
    url: jdbc:mysql://localhost:3306/mybatisplus_db?serverTimezone=UTC
    username: root
    password: root
  1. 書寫資料庫物體類
package com.itheima.domain;

import lombok.*;

@Data
public class User {
    private Long id;
    private String name;
    private String password;
    private Integer age;
    private String tel;

    public Long getId() {
        return id;
    }

    public void setId(Long id) {
        this.id = id;
    }

    public String getName() {
        return name;
    }

    public void setName(String name) {
        this.name = name;
    }

    public String getPassword() {
        return password;
    }

    public void setPassword(String password) {
        this.password = password;
    }

    public Integer getAge() {
        return age;
    }

    public void setAge(Integer age) {
        this.age = age;
    }

    public String getTel() {
        return tel;
    }

    public void setTel(String tel) {
        this.tel = tel;
    }


    @java.lang.Override
    public java.lang.String toString() {
        return "User{" +
                "id=" + id +
                ", name='" + name + '\'' +
                ", password='" + password + '\'' +
                ", age=" + age +
                ", tel='" + tel + '\'' +
                '}';
    }
}
  1. 資料層書寫
package com.itheima.dao;

import com.baomidou.mybatisplus.core.mapper.BaseMapper;
import com.itheima.domain.User;
import org.apache.ibatis.annotations.Mapper;

// @Mapper為了使掃描到該資料層包(SpringBoot中提及)
@Mapper
// 注意:MyBatisPlus不需要書寫方法,我們直接繼承BaseMapper類,并表明我們所使用的物體類即可
public interface UserDao extends BaseMapper<User> {
    // 不需要書寫方法,在BaseMapper類中為我們配置了大量的資料庫方法來查詢,新增,修改,洗掉
}
  1. 測驗
package com.itheima;

import com.baomidou.mybatisplus.core.metadata.IPage;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.itheima.dao.UserDao;
import com.itheima.domain.User;
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 Mybatisplus01QuickstartApplicationTests {

    @Autowired
    private UserDao userDao;

    // 我們只需要得到UserDao類,并呼叫其方法即可(MyBatisPlus提供方法)
    // 在這里我們僅呼叫selectById方法,當作測驗
    @Test
    void testGetById(){
        User user = userDao.selectById(2L);
        System.out.println(user);
    }
}

至此,我們的第一個MyBatisPlus案例就結束了

MyBatisPlus概述

在使用過MyBatisPlus后,我們就可以重新介紹一下MyBatisPlus了:

  • MyBatisPlus(MP)是基于MyBatis框架基礎上開發的增強型工具,旨在簡化開發,提高效率
  • 官網:MyBatis-Plus (baomidou.com)

MyBatisPlus特征:

  • 無侵入:制作增強,不做改變,不會對現有工程產生影響
  • 強大的CRUD操作:內置通用的Mapper,少量配置即可實作單表CRUD操作
  • 支持Lambda:撰寫查詢條件無需擔心欄位錯誤
  • 支持逐漸自動生成
  • 內置分頁插件

最后提及一句:MyBatisPlus是由國人開發,官網也是以中文書寫,具有中國風范~

標準資料層開發

我們在前面已經大致掌握了MyBatisPlus的具體操作流程,下面讓我們更加細膩的分析資料層開發

Lombok依賴坐標

在正式開始講解資料層開發前,為大家提供一個簡單可靠的依賴:

  • Lombok依賴

那么這個坐標具有什么作用呢

  • Lombok依賴可以用來簡化物體類的開發
  • Lombok,屬于Java類別庫,提供了一組注解,簡化POJO物體類開發

我們采用一個簡單的案例來展示:

  1. 首先我們需要匯入該坐標
        <dependency>
            <groupId>org.projectlombok</groupId>
            <artifactId>lombok</artifactId>
            <version>1.18.12</version>
            <scope>provided</scope>
        </dependency>
  1. 我們的物體類中產生多個新注解
package com.itheima.domain;

import lombok.*;

//lombok

@Data
public class User {
    private Long id;
    private String name;
    private String password;
    private Integer age;
    private String tel;
}
/*
lombok為我們提供了多個注解:

@Setter:提供所有set方法
@Getter:提供所有Get方法
@ToString:提供ToString重構方法
@NoArgsConstructor:無參構造
@AllArgsConstructor:有參構造

其中我們最常用的注解是:
@Data:包括了除建構式外的所有方法(Set,Get,ToString,hashCode,equals)
*/

標準資料層開發(簡單版)

首先我們來列出一些我們通常開發中會使用的資料層陳述句:

功能 MP介面
新增 int insert(T t)
洗掉 int deleteById(Serializable id)
修改 int updateById(T t)
根據id查詢 T selectById(Serializable id)
查詢全部 List selectList()

上述方法我們無需在資料層定義,直接測驗即可:

package com.itheima;

import com.baomidou.mybatisplus.core.metadata.IPage;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.itheima.dao.UserDao;
import com.itheima.domain.User;
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 Mybatisplus01QuickstartApplicationTests {

    // 自動裝配資料層
    @Autowired
    private UserDao userDao;

    // 注意:id的資料型別為LONG,數值后需要加L
    
    // 注意:下述部分方法需要回傳id,物體類,null
    
    // 新增
    @Test
    void testSave(){
        User user = new User();
        user.setName("黑馬程式員");
        user.setPassword("itheima");
        user.setAge(12);
        user.setTel("4006184000");
        userDao.insert(user);
    }

    // 洗掉
    @Test
    void testDelete(){
        userDao.deleteById(1L);
    }

    // 更新(注意:根據id進行更新,更新與原資料不同的數值,null值不進行更新)
    @Test
    void testUpdate(){
        User user = new User();
        user.setId(1L);
        user.setName("Tom888");
        user.setPassword("tom888");
        userDao.updateById(user);
    }

    // 根據id查詢
    @Test
    void testGetById(){
        User user = userDao.selectById(2L);
        System.out.println(user);
    }

	// 查詢全部
    @Test
    void testGetAll() {
        List<User> userList = userDao.selectList(null);
        System.out.println(userList);
    }

}

標準資料層開發(分頁查詢)

我們將分頁查詢單獨列為一個小節進行講解:

功能 MP介面
分頁查詢 IPage<T> selectPage(IPage<T> page)

MyBatisPlus的分頁查詢需要一些前置條件,我們下面一一講述:

  1. 添加攔截器,進行分頁操作:
// MyBatisPlus的分頁操作需要添加攔截器

// 我們在Java檔案夾下創建Config檔案夾,創建MPConfig的Java類作為配置類

package com.itheima.config;

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;

// 作為配置類,讓spring可以直接掃描
@Configuration
public class MpConfig {
    
    // 需要設定為Bean
    @Bean
    public MybatisPlusInterceptor mpInterceptor(){
        //1.定義Mp攔截器MybatisPlusInterceptor(相當于外層攔截器)
        MybatisPlusInterceptor mpInterceptor = new MybatisPlusInterceptor();
        //2.添加具體的攔截器PaginationInnerInterceptor(相當于在大攔截器中添加小攔截器)
        mpInterceptor.addInnerInterceptor(new PaginationInnerInterceptor());
        return mpInterceptor;
    }
}
  1. 直接測驗即可
package com.itheima;

import com.baomidou.mybatisplus.core.metadata.IPage;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.itheima.dao.UserDao;
import com.itheima.domain.User;
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 Mybatisplus01QuickstartApplicationTests {

    @Autowired
    private UserDao userDao;

    @Test
    void testGetByPage(){
       // selectPage需要兩個引數IPage和Wrapper,IPage具有Page的實作類,Wrapper我們會在后續講到,這里暫設為null
        
        //IPage物件封裝了分頁操作相關的資料,第一個引數為開始數,第二個數為本頁可展示資料數
        IPage page  = new Page(2,3);
        
        userDao.selectPage(page,null);
        
        // 下述為page本身攜帶的一些方法,用于查看相關資料
        System.out.println("當前頁碼值:"+page.getCurrent());
        System.out.println("每頁顯示數:"+page.getSize());
        System.out.println("一共多少頁:"+page.getPages());
        System.out.println("一共多少條資料:"+page.getTotal());
        System.out.println("資料:"+page.getRecords());
    }

}
  1. 查看日志
# 如果我們想要查看實際開發的資料庫陳述句,我們可以選擇開啟日志進行查看

# 查看日志方法設定在yaml組態檔中

# 開啟mp的日志(輸出到控制臺)
mybatis-plus:
  configuration:
    log-impl: org.apache.ibatis.logging.stdout.StdOutImpl

DQL編程控制

我們在前面已經講解了簡單的資料層開發,下面我們將會進一步講解DQL的編程內容

清除版本圖

在正式開始前,我們講一些簡單輕松的知識點:

  • 我們在每次開啟服務器后都會出現SpringBoot和MyBatisPlus的版本圖,有時會影響我們代碼的閱讀

那么我們該如何清除呢

  1. 設定logback.xml檔案
<!--我們在sources中新創一個spring config 檔案-->

<!--設定一個configuration雙標簽,不用填寫內容即可-->
<?xml version="1.0" encoding="UTF-8"?>
<configuration>
</configuration>
  1. 在yaml組態檔中做清除作業
# 我們只需要將spring和MyBatisPlus的banner設定為false即可關閉版本圖

# dataSource
spring:
  datasource:
    type: com.alibaba.druid.pool.DruidDataSource
    driver-class-name: com.mysql.cj.jdbc.Driver
    url: jdbc:mysql://localhost:3306/mybatisplus_db?serverTimezone=UTC
    username: root
    password: root
  main:
    banner-mode: off
# mp日志
mybatis-plus:
  configuration:
    log-impl: org.apache.ibatis.logging.stdout.StdOutImpl
  global-config:
    banner: false

基本條件查詢

在介紹條件查詢前,我們需要先來介紹Wrapper:

  • Wrapper屬于一種介面引數
  • Wrapper是我們的條件查詢中所攜帶的進行條件判斷的引數
  • 介面方法的引數中,會出現各種 Wrapper,比如 queryWrapper、updateWrapper 等

接下來我們就來介紹三種基本條件查詢:

  1. 按條件查詢
package com.itheima;

import com.baomidou.mybatisplus.core.conditions.Wrapper;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.itheima.dao.UserDao;
import com.itheima.domain.User;
import com.itheima.domain.query.UserQuery;
import org.junit.jupiter.api.Test;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.test.context.SpringBootTest;

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

@SpringBootTest
class Mybatisplus02DqlApplicationTests {

    @Autowired
    private UserDao userDao;

    @Test
    void testGetAll() {
        //方式一:按條件查詢
        
        // 我們的條件查詢一般采用QueryWrapper型別的類來創造Wrapper條件判斷引數
        QueryWrapper qw = new QueryWrapper();
        // 我們采用QueryWrapper的一些方法來進行給予判斷條件,后續我們會進行介紹
        // 這里采用lt小于方法,后面跟String型別字串代表資料庫列名,在跟數值表示值
        qw.lt("age",18);
        // 我們采用userDao的selectList方法根據qw條件判斷機制來進行獲取資料
        // 獲取了User數值的List,并列印即可
        List<User> userList = userDao.selectList(qw);
        System.out.println(userList);

    }

}
  1. lambda格式按條件查詢(方法版)
package com.itheima;

import com.baomidou.mybatisplus.core.conditions.Wrapper;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.itheima.dao.UserDao;
import com.itheima.domain.User;
import com.itheima.domain.query.UserQuery;
import org.junit.jupiter.api.Test;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.test.context.SpringBootTest;

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

@SpringBootTest
class Mybatisplus02DqlApplicationTests {

    @Autowired
    private UserDao userDao;

    @Test
    void testGetAll() {

        //方式二:lambda格式按條件查詢
        
        QueryWrapper<User> qw = new QueryWrapper<User>();
        // MyBatisPlus可支持Lambda運算式,我們使用lambda方法使后續操作均變為Lambda運算式形式
        // 我們的String資料庫列名可以采用Lambda運算式形式書寫
        qw.lambda().lt(User::getAge, 10);
        List<User> userList = userDao.selectList(qw);
        System.out.println(userList);

    }

}
  1. lambda格式按條件查詢(繼承類版)
package com.itheima;

import com.baomidou.mybatisplus.core.conditions.Wrapper;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.itheima.dao.UserDao;
import com.itheima.domain.User;
import com.itheima.domain.query.UserQuery;
import org.junit.jupiter.api.Test;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.test.context.SpringBootTest;

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

@SpringBootTest
class Mybatisplus02DqlApplicationTests {

    @Autowired
    private UserDao userDao;

    @Test
    void testGetAll() {
        
        //方式三:lambda格式按條件查詢
        
        // 這里直接繼承LambdaQueryWrapper,后續操作可以直接采用Lambda運算式,不用攜帶方法lambda
        LambdaQueryWrapper<User> lqw = new LambdaQueryWrapper<User>();
        lqw.lt(User::getAge, 10);
        List<User> userList = userDao.selectList(lqw);
        System.out.println(userList);

    }

}

除了上面三種基本條件查詢外,我們可以發現條件查詢是可以疊加使用的,主要分為兩種疊加方式:

  1. 正常疊加
package com.itheima;

import com.baomidou.mybatisplus.core.conditions.Wrapper;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.itheima.dao.UserDao;
import com.itheima.domain.User;
import com.itheima.domain.query.UserQuery;
import org.junit.jupiter.api.Test;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.test.context.SpringBootTest;

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

@SpringBootTest
class Mybatisplus02DqlApplicationTests {

    @Autowired
    private UserDao userDao;

    @Test
    void testGetAll() {

        // 10到30歲之間
        LambdaQueryWrapper<User> lqw = new LambdaQueryWrapper<User>();
        // 依次分開書寫
        lqw.lt(User::getAge, 30);
        lqw.gt(User::getAge, 10);
        List<User> userList = userDao.selectList(lqw);
        System.out.println(userList);

    }

}
  1. 鏈式疊加
package com.itheima;

import com.baomidou.mybatisplus.core.conditions.Wrapper;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.itheima.dao.UserDao;
import com.itheima.domain.User;
import com.itheima.domain.query.UserQuery;
import org.junit.jupiter.api.Test;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.test.context.SpringBootTest;

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

@SpringBootTest
class Mybatisplus02DqlApplicationTests {

    @Autowired
    private UserDao userDao;

    @Test
    void testGetAll() {

        // 10到30歲之間
        LambdaQueryWrapper<User> lqw = new LambdaQueryWrapper<User>();
        // 鏈式疊加書寫
        lqw.lt(User::getAge, 30).gt(User::getAge, 10);
        List<User> userList = userDao.selectList(lqw);
        System.out.println(userList);

    }

}

最后我們還要介紹兩種組合查詢條件形式:

  1. 并且(and)
package com.itheima;

import com.baomidou.mybatisplus.core.conditions.Wrapper;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.itheima.dao.UserDao;
import com.itheima.domain.User;
import com.itheima.domain.query.UserQuery;
import org.junit.jupiter.api.Test;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.test.context.SpringBootTest;

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

@SpringBootTest
class Mybatisplus02DqlApplicationTests {

    @Autowired
    private UserDao userDao;

    @Test
    void testGetAll() {

        //并且關系
        LambdaQueryWrapper<User> lqw = new LambdaQueryWrapper<User>();
        //并且關系:10到30歲之間(直接鏈式書寫即可)
        lqw.lt(User::getAge, 30).gt(User::getAge, 10);
        List<User> userList = userDao.selectList(lqw);
        System.out.println(userList);

    }

}
  1. 或者(or)
package com.itheima;

import com.baomidou.mybatisplus.core.conditions.Wrapper;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.itheima.dao.UserDao;
import com.itheima.domain.User;
import com.itheima.domain.query.UserQuery;
import org.junit.jupiter.api.Test;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.test.context.SpringBootTest;

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

@SpringBootTest
class Mybatisplus02DqlApplicationTests {

    @Autowired
    private UserDao userDao;

    @Test
    void testGetAll() {

        //或者關系
        LambdaQueryWrapper<User> lqw = new LambdaQueryWrapper<User>();
        //或者關系:小于10歲或者大于30歲(在條件之間采用or方法來隔離)
        lqw.lt(User::getAge, 10).or().gt(User::getAge, 30);
        List<User> userList = userDao.selectList(lqw);
        System.out.println(userList);

    }

}

空值處理

我們在做實際專案處理時,會出現各種查詢框架

例如價格查詢搜索產品,但我們可能不會同時給出最低價限制和最高價限制

我們以代碼來做一個簡單示例:

package com.itheima;

import com.baomidou.mybatisplus.core.conditions.Wrapper;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.itheima.dao.UserDao;
import com.itheima.domain.User;
import com.itheima.domain.query.UserQuery;
import org.junit.jupiter.api.Test;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.test.context.SpringBootTest;

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

@SpringBootTest
class Mybatisplus02DqlApplicationTests {

    @Autowired
    private UserDao userDao;
    
    @Test
    void testGetAll() {
		// 模擬頁面傳遞過來的查詢資料
        UserQuery uq = new UserQuery();
        // 如果我們下面的資料有一個沒有設定,就會導致查詢陳述句中的?沒有填充,導致搜索失敗
        uq.setAge(10);
        uq.setAge2(null);

        // null判定
        LambdaQueryWrapper<User> lqw = new LambdaQueryWrapper<User>();
        lqw.lt(User::getAge, uq.getAge2());
        lqw.gt(User::getAge, uq.getAge());
        List<User> userList = userDao.selectList(lqw);
        System.out.println(userList)

    }

}

在之前我們的null值處理大部分都是采用if陳述句來進行判斷:

package com.itheima;

import com.baomidou.mybatisplus.core.conditions.Wrapper;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.itheima.dao.UserDao;
import com.itheima.domain.User;
import com.itheima.domain.query.UserQuery;
import org.junit.jupiter.api.Test;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.test.context.SpringBootTest;

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

@SpringBootTest
class Mybatisplus02DqlApplicationTests {

    @Autowired
    private UserDao userDao;
    
    @Test
    void testGetAll() {
		// 模擬頁面傳遞過來的查詢資料
        UserQuery uq = new UserQuery();
		// 可能出現有任意一個數沒有賦值
        uq.setAge(10);
        uq.setAge2(null);

        // null判定
        LambdaQueryWrapper<User> lqw = new LambdaQueryWrapper<User>();
        lqw.lt(User::getAge, uq.getAge2());
        
        // 正常我們采用if來進行判斷是否有值,若有值則加入操作
        // 但當if陳述句過多,導致代碼冗雜
        if( null != uq.getAge()) {
            lqw.gt(User::getAge, uq.getAge());
        }
        List<User> userList = userDao.selectList(lqw);
        System.out.println(userList);

    }

}

MyBatisPlus給出了一種新的判定方法來決定是否加載該陳述句:

package com.itheima;

import com.baomidou.mybatisplus.core.conditions.Wrapper;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.itheima.dao.UserDao;
import com.itheima.domain.User;
import com.itheima.domain.query.UserQuery;
import org.junit.jupiter.api.Test;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.test.context.SpringBootTest;

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

@SpringBootTest
class Mybatisplus02DqlApplicationTests {

    @Autowired
    private UserDao userDao;
    
    @Test
    void testGetAll() {
		// 模擬頁面傳遞過來的查詢資料
        UserQuery uq = new UserQuery();
        uq.setAge(10);
        uq.setAge2(30);

		// LambdaQueryWrapper的各種方法中均攜帶了一個判定條件在最前面的引數中,當成立執行后續操作,不成立直接跳過
        LambdaQueryWrapper<User> lqw = new LambdaQueryWrapper<User>();
        // 先判定第一個引數是否為true,如果為true連接當前條件
        lqw.lt(null != uq.getAge2(),User::getAge, uq.getAge2());
        lqw.gt(null != uq.getAge(),User::getAge, uq.getAge());
        List<User> userList = userDao.selectList(lqw);
        System.out.println(userList);

    }

}

查詢投影

我們選擇性的查詢資料庫列稱為查詢投影,接下來讓我們來介紹查詢投影的實作方法

查詢投影的實作我們大致分為兩種型別:

  1. 查詢結果包含模型類中部分屬性
package com.itheima;

import com.baomidou.mybatisplus.core.conditions.Wrapper;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.itheima.dao.UserDao;
import com.itheima.domain.User;
import com.itheima.domain.query.UserQuery;
import org.junit.jupiter.api.Test;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.test.context.SpringBootTest;

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

@SpringBootTest
class Mybatisplus02DqlApplicationTests {

    @Autowired
    private UserDao userDao;
    
    @Test
    void testGetAll() {
        // 查詢投影
    
    	// 當我們所查詢的內容屬于物體類中包含的屬性,我們可以采用QW或LambdaQW來實作
    	// 我們大部分采用LambdaQW來實作,因為帶有自動識別,不易出錯
        LambdaQueryWrapper<User> lqw = new LambdaQueryWrapper<User>();
    	// 我們采用select方法來添加查詢種類,LambdaQueryWrapper采用Lambda運算式添加
        lqw.select(User::getId,User::getName,User::getAge);
        QueryWrapper<User> lqw = new QueryWrapper<User>();
        // 我們采用select方法來添加查詢種類,QueryWrapper采用String添加
        lqw.select("id","name","age","tel");
        List<User> userList = userDao.selectList(lqw);
        System.out.println(userList);

    }

}
  1. 查詢結果包含模型類中未定義屬性
package com.itheima;

import com.baomidou.mybatisplus.core.conditions.Wrapper;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.itheima.dao.UserDao;
import com.itheima.domain.User;
import com.itheima.domain.query.UserQuery;
import org.junit.jupiter.api.Test;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.test.context.SpringBootTest;

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

@SpringBootTest
class Mybatisplus02DqlApplicationTests {

    @Autowired
    private UserDao userDao;
    
    @Test
    void testGetAll() {
        // 查詢投影
    
        // 未定義的屬性我們只能采用QueryWrapper的String字串來書寫,例如count(*)和分組條件
        QueryWrapper<User> lqw = new QueryWrapper<User>();
        lqw.select("count(*) as count, tel");
        // QueryWrapper提供了分組方法groupBy,引數為String型別的資料庫列名
        lqw.groupBy("tel");
        List<Map<String, Object>> userList = userDao.selectMaps(lqw);
        System.out.println(userList);

    }

}

查詢條件展示

首先我們給出所有查詢條件官網鏈接:條件構造器 | MyBatis-Plus (baomidou.com)

如果有需要可以上網查詢相關構造方法

下面我們僅對一些常用查詢條件進行展示:

package com.itheima;

import com.baomidou.mybatisplus.core.conditions.Wrapper;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.itheima.dao.UserDao;
import com.itheima.domain.User;
import com.itheima.domain.query.UserQuery;
import org.junit.jupiter.api.Test;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.test.context.SpringBootTest;

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

@SpringBootTest
class Mybatisplus02DqlApplicationTests {

    @Autowired
    private UserDao userDao;

    @Test
    void testGetAll() {

        //條件查詢
        LambdaQueryWrapper<User> lqw = new LambdaQueryWrapper<User>();
        // eq等同于=
        lqw.eq(User::getName,"Jerry").eq(User::getPassword,"jerry");
        User loginUser = userDao.selectOne(lqw);
        System.out.println(loginUser);

        LambdaQueryWrapper<User> lqw = new LambdaQueryWrapper<User>();
        //范圍查詢 lt le gt ge eq between
        lqw.between(User::getAge,10,30);
        List<User> userList = userDao.selectList(lqw);
        System.out.println(userList);

        LambdaQueryWrapper<User> lqw = new LambdaQueryWrapper<User>();
        //模糊匹配 like
        lqw.likeLeft(User::getName,"J");
        List<User> userList = userDao.selectList(lqw);
        System.out.println(userList);

		// 查詢全部
        LambdaQueryWrapper<User> lqw = new LambdaQueryWrapper<User>();
        List<User> userList = userDao.selectList(lqw);
        System.out.println(userList);

    }

}

映射處理

最后介紹的依舊是我們在MyBatis中也出現的老問題:

  • 當我們的實作類和資料庫表出現不同點時我們該如何處理

我們在下面分為幾種情況來講解:

  1. 表名與編碼開發設計不同步
// 假設我們的資料庫表名為tbl_user,但我們的物體類設計為User

package com.itheima.domain;

import com.baomidou.mybatisplus.annotation.TableField;
import com.baomidou.mybatisplus.annotation.TableName;
import lombok.Data;

// 采用注解@TableName,后面跟對應的資料庫表名
@TableName("tbl_user")
public class User {
    private Long id;
    private String name;
    private String password;
    private Integer age;
    private String tel;
}
  1. 列名與編碼開發設計不同步
// 假設我們的資料庫密碼設計為pwd,但是我們的物體類密碼屬性設計為password

package com.itheima.domain;

import com.baomidou.mybatisplus.annotation.TableField;
import com.baomidou.mybatisplus.annotation.TableName;
import lombok.Data;

//lombok
@Data
@TableName("tbl_user")
public class User {
    private Long id;
    private String name;
    
    // 采用@TableField注解,后面采用屬性value=https://www.cnblogs.com/qiuluoyuweiliang/p/資料庫列名
    @TableField(value ="pwd")
    private String password;
    
    private Integer age;
    private String tel;
}
  1. 該列不應當被列印時
// 例如我們的pwd密碼,在查詢時不應當被查詢,但是我們采用select * from tbl_user來查詢,如何屏蔽

package com.itheima.domain;

import com.baomidou.mybatisplus.annotation.TableField;
import com.baomidou.mybatisplus.annotation.TableName;
import lombok.Data;

//lombok
@Data
@TableName("tbl_user")
public class User {
    private Long id;
    private String name;
    
    // 采用@TableField注解,后面采用屬性select設定為false,即為不可查詢
    @TableField(value = "https://www.cnblogs.com/qiuluoyuweiliang/p/pwd",select = false)
    private String password;
    
    private Integer age;
    private String tel;
}
  1. 當物體類中出現資料庫中不存在的列時
// 例如我們設計了一個屬性online判斷是否在線,不用放于資料庫中,我們該如何在select * 中去除該屬性

package com.itheima.domain;

import com.baomidou.mybatisplus.annotation.TableField;
import com.baomidou.mybatisplus.annotation.TableName;
import lombok.Data;

//lombok
@Data
@TableName("tbl_user")
public class User {
    private Long id;
    private String name;
    @TableField(value = "https://www.cnblogs.com/qiuluoyuweiliang/p/pwd",select = false)
    private String password;
    private Integer age;
    private String tel;
    
    // 采用@TableField注解,后面跟屬性exist設定為false,則判斷該屬性不存在于資料庫中
    @TableField(exist = false)
    private Integer online;
}

我們將上述內容分離出來主要解釋兩個注解:

  1. @TableName
  • 名稱:@TableName
  • 型別:類注解
  • 位置:模型類定義上方
  • 作用:設定當前類對應的資料庫表關系
  • 相關屬性:value設定資料庫表名稱
  1. @TableField
  • 名稱:@TableField
  • 型別:屬性注解
  • 位置:模型類屬性定義上方
  • 作用:設定當前屬性眾多關系
  • 相關屬性:value設定資料庫欄位名稱,exist設定屬性在資料庫欄位中是否存在,select設定屬性是否參與查詢

DML編程控制

這一章節我們來講一些MyBatisPlus中經常用到的操作,下面我們一一介紹

ID生成策略控制

我們在實際開發中會有需要ID生成需求,對于不同的情況需要采取不同的ID生成方法:

  • 員工編號:遞增ID生成
  • 快遞單號:地區ID生成
  • 網路編號:隨機ID生成

因此MyBatisPlus提供了一種新的注解來實作這類需求:

  • 名稱:@TableId
  • 型別:屬性注解
  • 位置:模型類中用于表示主鍵的屬性定義上方
  • 作用:設定當前類中主鍵屬性的生成策略
  • 相關屬性:value設定資料庫主鍵名稱,type設定主鍵生成策略具體參考IdType列舉值

ID生成策略列舉值:

  • AUTO(0):使用資料庫id自增策略控制id生成
  • NONE(1):不設定ID生成策略
  • INPUT(2):用戶手工輸入ID
  • ASSIGN_ID(3):雪花演算法生成ID(可兼容數值型與字串型)
  • ASSIGN_UUID(4):以UUID生成演算法作為ID生成策略

我們給出示例演示:

package com.itheima.domain;

import com.baomidou.mybatisplus.annotation.TableField;
import com.baomidou.mybatisplus.annotation.TableLogic;
import com.baomidou.mybatisplus.annotation.Version;
import lombok.Data;

@Data
//設定表名映射關系
@TableName("tbl_user")
public class User {
    //設定主鍵生成策略(這里設定為自增)
    @TableId(type = IdType.AUTO)
    private Long id;
    private String name;
    @TableField(value = "https://www.cnblogs.com/qiuluoyuweiliang/p/pwd",select = false)
    private String password;
    private Integer age;
    private String tel;
    @TableField(exist = false)
    private Integer online;
    private Integer deleted;
    private Integer version;
}

我們也可以同一設定@TableId的type屬性,使整個專案的@TableId都以一種形態執行:

# dataSource
spring:
  datasource:
    type: com.alibaba.druid.pool.DruidDataSource
    driver-class-name: com.mysql.cj.jdbc.Driver
    url: jdbc:mysql://localhost:3306/mybatisplus_db?serverTimezone=UTC
    username: root
    password: root
  main:
    banner-mode: off
# mp日志
mybatis-plus:
  configuration:
    log-impl: org.apache.ibatis.logging.stdout.StdOutImpl
  global-config:
    banner: false
    db-config:
      id-type: assign_id # 設定為雪花演算法設定ID

多記錄操作

我們在實際開發中常常會進行多條記錄操作:

  • 根據主鍵洗掉多條操作
  • 根據主鍵查詢多條操作

MyBatisPlus也為我們提供了相對應的方法:

package com.itheima;

import com.baomidou.mybatisplus.core.metadata.IPage;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.itheima.dao.UserDao;
import com.itheima.domain.User;
import org.junit.jupiter.api.Test;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.test.context.SpringBootTest;

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

@SpringBootTest
class Mybatisplus03DqlApplicationTests {

    @Autowired
    private UserDao userDao;

    @Test
    void testDelete(){
        //洗掉指定多條資料
        //deleteBatchIds引數為陣列形式,我們提供id的陣列即可
        List<Long> list = new ArrayList<>();
        list.add(1402551342481838081L);
        list.add(1402553134049501186L);
        list.add(1402553619611430913L);
        userDao.deleteBatchIds(list);
    }
    
    @Test
    void testSelect()}{
        //查詢指定多條資料
    	//selectBatchIds引數為陣列形式,我們提供id的陣列即可
        List<Long> list = new ArrayList<>();
        list.add(1L);
        list.add(3L);
        list.add(4L);
        userDao.selectBatchIds(list);
	}

}

邏輯洗掉

我們在實際開發中面對專案的洗掉操作有時并非是真正的洗掉操作:

  • 例如對于一些資料的存盤,我們需要在年終總結中計算總產量,所以所有利益收入不能洗掉
  • 但對于一些離職的員工,關于他們的資料需要暫時性洗掉,因而產生矛盾

因而我們提出了邏輯洗掉的概念:

  • 我們在總串列中添加一個屬性deleted來設定是否被洗掉
  • 當deleted為1時,當作資料洗掉;當deleted為1時,當作資料存在
  • 我們在實際開發中以一種虛擬的洗掉思想(邏輯洗掉)來代替真正的資料洗掉

下面我們來講解如何在MyBatisPlus中實作這種思想:

  1. 資料庫中添加deleted列
ALTER TABLE tb_user ADD deleted int(1) DEFAULT 0;
  1. 物體庫中添加deleted屬性,并用注解注明為邏輯洗掉屬性
package com.itheima.domain;

import com.baomidou.mybatisplus.annotation.TableField;
import com.baomidou.mybatisplus.annotation.TableLogic;
import com.baomidou.mybatisplus.annotation.Version;
import lombok.Data;

@Data
//設定表名映射關系
@TableName("tbl_user")
public class User {
    //設定主鍵生成策略
    @TableId(type = IdType.ASSIGN_ID)
    private Long id;
    private String name;
    @TableField(value = "https://www.cnblogs.com/qiuluoyuweiliang/p/pwd",select = false)
    private String password;
    private Integer age;
    private String tel;
    @TableField(exist = false)
    private Integer online;
    //邏輯洗掉欄位,標記當前記錄是否被洗掉(value原值,delval修改值)
    @TableLogic(value = "https://www.cnblogs.com/qiuluoyuweiliang/p/0" ,delval = "1")
    private Integer deleted;
}

/*
@TableLogic
在設定之后,我們采用delete方法時,不會直接洗掉資料,而是將該資料值從value變為delval
類似于:UPDATE tbl_user SET deleted = 1 WHERE id = ? AND deleted = 0;
*/

同樣,我們的邏輯洗掉值也可以進行統一設定:

# dataSource
spring:
  datasource:
    type: com.alibaba.druid.pool.DruidDataSource
    driver-class-name: com.mysql.cj.jdbc.Driver
    url: jdbc:mysql://localhost:3306/mybatisplus_db?serverTimezone=UTC
    username: root
    password: root
  main:
    banner-mode: off
# mp日志
mybatis-plus:
  configuration:
    log-impl: org.apache.ibatis.logging.stdout.StdOutImpl
  global-config:
    banner: false
    db-config:
      id-type: assign_id
      table-prefix: tbl_
      # 邏輯洗掉欄位名
      logic-delete-field: deleted
      # 邏輯洗掉字面值:未洗掉為0
      logic-not-delete-value: 0
      # 邏輯洗掉字面值:洗掉為1
      logic-delete-value: 1

樂觀鎖

我們在業務開發中也會遇到多執行緒的問題:

  • 例如我們的秒殺活動,在之前多執行緒中也有提及過的問題
  • 如果我們不希望我們的剩余商品數變為負數,那么就需要設定Lock來解決這個問題

首先我們來講解一下樂觀鎖的基本概念:

  • 樂觀鎖首先讀取當前該商品的狀態
  • 然后利用當前商品的狀態為條件來修改商品狀態,并且將該商品狀態進行修改
  • 如果用戶A和用戶B同時讀取商品狀態,當用戶A的WHERE條件成立后修改商品,則用戶B的WHERE條件就不再成立無法修改

在MyBatisPlus中我們采用樂觀鎖的概念來解決:

  1. 在資料庫中新添version屬性
ALTER TABLE tb_user ADD version int(11) DEFAULT 1;
  1. 物體類中新添version屬性并加上注解
package com.itheima.domain;

import com.baomidou.mybatisplus.annotation.TableField;
import com.baomidou.mybatisplus.annotation.TableLogic;
import com.baomidou.mybatisplus.annotation.Version;
import lombok.Data;

@Data
//設定表名映射關系
@TableName("tbl_user")
public class User {
    @TableId(type = IdType.ASSIGN_ID)
    private Long id;
    private String name;
    @TableField(value = "https://www.cnblogs.com/qiuluoyuweiliang/p/pwd",select = false)
    private String password;
    private Integer age;
    private String tel;
    @TableField(exist = false)
    private Integer online;
    @TableLogic(value = "https://www.cnblogs.com/qiuluoyuweiliang/p/0" ,delval = "1")
    private Integer deleted;
    
    // version版本注解(樂觀鎖)
    @Version
    private Integer version;
}
  1. 使用攔截器
/*
我們來講解一下為什么需要使用攔截器
我們將前面我們介紹的樂觀鎖概念轉化為陳述句:

SELETE version FROM tbl_user

UPDATE tbl_user SET ...(用戶修改) version=version+1 WHERE id = ? AND version = version(我們之前讀取的version)

倘若用戶操作前有其他用戶操作,那么version就會發生變化,導致用戶無法找到對應的資料,無法操作

因為我們需要對前面的version進行修改,我們需要將陳述句攔截下來進行一定修改,所以這里采用攔截器
*/

package com.itheima.config;

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

@Configuration
public class MpConfig {
    @Bean
    public MybatisPlusInterceptor mpInterceptor() {
        //1.定義Mp攔截器
        MybatisPlusInterceptor mpInterceptor = new MybatisPlusInterceptor();
        //2.添加具體的攔截器
        mpInterceptor.addInnerInterceptor(new PaginationInnerInterceptor());
        //3.添加樂觀鎖攔截器
        mpInterceptor.addInnerInterceptor(new OptimisticLockerInnerInterceptor());
        return mpInterceptor;
    }
}
  1. 測驗
package com.itheima;

import com.baomidou.mybatisplus.core.metadata.IPage;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.itheima.dao.UserDao;
import com.itheima.domain.User;
import org.junit.jupiter.api.Test;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.test.context.SpringBootTest;

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

@SpringBootTest
class Mybatisplus03DqlApplicationTests {

    @Autowired
    private UserDao userDao;

    @Test
    void testUpdate(){
        
        // 我們設定一個實體User,id為1,version為1
        User user = new User();
        user.setId(1L);
        user.setName("Jock666");
        user.setVersion(1);
        userDao.updateById(user);

        // 我們用user,user2來當作兩個用戶
        
        // 假設兩個用戶同時讀取資料
        User user = userDao.selectById(3L);     //version=1

        User user2 = userDao.selectById(3L);    //version=1

        // user用戶首先進行操作(這時 實體version為1 操作成立 ,操作結束后version變為2)
        // UPDATE tbl_user SET ...(用戶修改) version=2 WHERE id = 1 AND version = 1
        user.setName("Jock aaa");
        userDao.updateById(user2);              

		// user2用戶開始操作(這時 實體version為2 但前面讀取的version為1,讀取不到資料,無法操作)
        // UPDATE tbl_user SET ...(用戶修改) version=2 WHERE id = 1 AND version = 1(已讀取不到資料)
        user2.setName("Jock bbb");
        userDao.updateById(user);               

    }

}

結束語

好的,關于MyBatisPlus的內容就介紹到這里,希望能為你帶來幫助!

附錄

該文章屬于學習內容,具體參考B站黑馬程式員李老師的SSM框架課程

這里附上鏈接:MyBatisPlus-01-MybatisPlus入門案例_嗶哩嗶哩_bilibili

轉載請註明出處,本文鏈接:https://www.uj5u.com/ruanti/516446.html

標籤:架構設計

上一篇:現在能夠以角度從物件讀取資料

下一篇:初識設計模式 - 觀察者模式

標籤雲
其他(157675) Python(38076) JavaScript(25376) Java(17977) C(15215) 區塊鏈(8255) C#(7972) AI(7469) 爪哇(7425) MySQL(7132) html(6777) 基礎類(6313) sql(6102) 熊猫(6058) PHP(5869) 数组(5741) R(5409) Linux(5327) 反应(5209) 腳本語言(PerlPython)(5129) 非技術區(4971) Android(4554) 数据框(4311) css(4259) 节点.js(4032) C語言(3288) json(3245) 列表(3129) 扑(3119) C++語言(3117) 安卓(2998) 打字稿(2995) VBA(2789) Java相關(2746) 疑難問題(2699) 细绳(2522) 單片機工控(2479) iOS(2429) ASP.NET(2402) MongoDB(2323) 麻木的(2285) 正则表达式(2254) 字典(2211) 循环(2198) 迅速(2185) 擅长(2169) 镖(2155) 功能(1967) .NET技术(1958) Web開發(1951) python-3.x(1918) HtmlCss(1915) 弹簧靴(1913) C++(1909) xml(1889) PostgreSQL(1872) .NETCore(1853) 谷歌表格(1846) Unity3D(1843) for循环(1842)

熱門瀏覽
  • 面試突擊第一季,第二季,第三季

    第一季必考 https://www.bilibili.com/video/BV1FE411y79Y?from=search&seid=15921726601957489746 第二季分布式 https://www.bilibili.com/video/BV13f4y127ee/?spm_id_fro ......

    uj5u.com 2020-09-10 05:35:24 more
  • 第三單元作業總結

    1.前言 這應該是本學期最后一次寫作業總結了吧。總體來說,對作業的節奏也差不多掌握了,作業做起來的效率也更高了。雖然和之前的作業一樣,作業中都要用到新的知識,但是相比之前,更加懂得了如何利用工具以及資料。雖然之間卡過殼,但總體而言,這幾次作業還算完成的比較好。 2.作業程序總結 相比前兩個單元,此單 ......

    uj5u.com 2020-09-10 05:35:41 more
  • 北航OO(2020)第四單元博客作業暨課程總結博客

    北航OO(2020)第四單元博客作業暨課程總結博客 本單元作業的架構設計 在本單元中,由于UML圖具有比較清晰的樹形結構,因此我對其中需要進行查詢操作的元素進行了包裝,在樹的父節點中存盤所有孩子的參考。考慮到性能問題,我采用了快取機制,一次查詢后盡可能快取已經遍歷過的資訊,以減少遍歷次數。 本單元我 ......

    uj5u.com 2020-09-10 05:35:48 more
  • BUAA_OO_第四單元

    一、UML決議器設計 ? 先看下題目:第四單元實作一個基于JDK 8帶有效性檢查的UML(Unified Modeling Language)類圖,順序圖,狀態圖分析器 MyUmlInteraction,實際上我們要建立一個有向圖模型,UML中的物件(元素)可能與同級元素連接,也可與低級元素相連形成 ......

    uj5u.com 2020-09-10 05:35:54 more
  • 6.1邏輯運算子

    邏輯運算子 1. && 短路與 運算式1 && 運算式2 01.運算式1為true并且運算式2也為true 整體回傳為true 02.運算式1為false,將不會執行運算式2 整體回傳為false 03.只要有一個運算式為false 整體回傳為false 2. || 短路或 運算式1 || 運算式2 ......

    uj5u.com 2020-09-10 05:35:56 more
  • BUAAOO 第四單元 & 課程總結

    1. 第四單元:StarUml檔案決議 本單元采用了圖模型決議UML。 UML檔案可以抽象為圖、子圖、邊的邏輯結構。 在實作中,圖的節點包括類、介面、屬性,子圖包括狀態圖、順序圖等。 采用了三次遍歷UML元素的方法建圖,第一遍遍歷建點,第二、三次遍歷設定屬性、連邊,實作圖物件的初始化。這里借鑒了一些 ......

    uj5u.com 2020-09-10 05:36:06 more
  • 談談我對C# 多型的理解

    面向物件三要素:封裝、繼承、多型。 封裝和繼承,這兩個比較好理解,但要理解多型的話,可就稍微有點難度了。今天,我們就來講講多型的理解。 我們應該經常會看到面試題目:請談談對多型的理解。 其實呢,多型非常簡單,就一句話:呼叫同一種方法產生了不同的結果。 具體實作方式有三種。 一、多載 多載很簡單。 p ......

    uj5u.com 2020-09-10 05:36:09 more
  • Python 資料驅動工具:DDT

    背景 python 的unittest 沒有自帶資料驅動功能。 所以如果使用unittest,同時又想使用資料驅動,那么就可以使用DDT來完成。 DDT是 “Data-Driven Tests”的縮寫。 資料:http://ddt.readthedocs.io/en/latest/ 使用方法 dd. ......

    uj5u.com 2020-09-10 05:36:13 more
  • Python里面的xlrd模塊詳解

    那我就一下面積個問題對xlrd模塊進行學習一下: 1.什么是xlrd模塊? 2.為什么使用xlrd模塊? 3.怎樣使用xlrd模塊? 1.什么是xlrd模塊? ?python操作excel主要用到xlrd和xlwt這兩個庫,即xlrd是讀excel,xlwt是寫excel的庫。 今天就先來說一下xl ......

    uj5u.com 2020-09-10 05:36:28 more
  • 當我們創建HashMap時,底層到底做了什么?

    jdk1.7中的底層實作程序(底層基于陣列+鏈表) 在我們new HashMap()時,底層創建了默認長度為16的一維陣列Entry[ ] table。當我們呼叫map.put(key1,value1)方法向HashMap里添加資料的時候: 首先,呼叫key1所在類的hashCode()計算key1 ......

    uj5u.com 2020-09-10 05:36:38 more
最新发布
  • 【中介者設計模式詳解】C/Java/JS/Go/Python/TS不同語言實作

    * 中介者模式是一種行為型設計模式,它可以用來減少類之間的直接依賴關系,
    * 將物件之間的通信封裝到一個中介者物件中,從而使得各個物件之間的關系更加松散。
    * 在中介者模式中,物件之間不再直接相互互動,而是通過中介者來中轉訊息。 ......

    uj5u.com 2023-04-20 08:20:47 more
  • 露天煤礦現場調研和交流案例分享

    他們集團的資訊化公司及研究院在一個礦區正在做智能礦山的統一平臺的 試點,專案投資大概1億,包括了礦山的各方面的內容,顯示得我們這次交流有點多余。他們2年前開始做智能礦山的規劃,有很多煤礦行業專家的加持,他們的描述是非常完美,但是去年底應該上線的平臺,現在還沒有看到影子。他們確實有很多場景需求,但是被... ......

    uj5u.com 2023-04-20 08:20:25 more
  • 《社區人員管理》實戰案例設計&個人案例分享

    設計是一個讓人夢想成真程序,開始編碼、測驗、除錯之前進行需求分析和架構設計,才能保證關鍵方面都做正確 ......

    uj5u.com 2023-04-20 08:20:17 more
  • 軟體架構生態化-多角色交付的探索實踐

    作為一個技術架構師,不僅僅要緊跟行業技術趨勢,還要結合研發團隊現狀及痛點,探索新的交付方案。在日常中,你是否遇到如下問題 “ 業務需求排期長研發是瓶頸;非研發角色感受不到研發技改提效的變化;引入ISV 團隊又擔心質量和安全,培訓周期長“等等,基于此我們探索了一種新的技術體系及交付方案來解決如上問題。 ......

    uj5u.com 2023-04-20 08:20:10 more
  • 【中介者設計模式詳解】C/Java/JS/Go/Python/TS不同語言實作

    * 中介者模式是一種行為型設計模式,它可以用來減少類之間的直接依賴關系,
    * 將物件之間的通信封裝到一個中介者物件中,從而使得各個物件之間的關系更加松散。
    * 在中介者模式中,物件之間不再直接相互互動,而是通過中介者來中轉訊息。 ......

    uj5u.com 2023-04-20 08:19:44 more
  • 露天煤礦現場調研和交流案例分享

    他們集團的資訊化公司及研究院在一個礦區正在做智能礦山的統一平臺的 試點,專案投資大概1億,包括了礦山的各方面的內容,顯示得我們這次交流有點多余。他們2年前開始做智能礦山的規劃,有很多煤礦行業專家的加持,他們的描述是非常完美,但是去年底應該上線的平臺,現在還沒有看到影子。他們確實有很多場景需求,但是被... ......

    uj5u.com 2023-04-20 08:19:07 more
  • 《社區人員管理》實戰案例設計&個人案例分享

    設計是一個讓人夢想成真程序,開始編碼、測驗、除錯之前進行需求分析和架構設計,才能保證關鍵方面都做正確 ......

    uj5u.com 2023-04-20 08:18:57 more
  • 軟體架構生態化-多角色交付的探索實踐

    作為一個技術架構師,不僅僅要緊跟行業技術趨勢,還要結合研發團隊現狀及痛點,探索新的交付方案。在日常中,你是否遇到如下問題 “ 業務需求排期長研發是瓶頸;非研發角色感受不到研發技改提效的變化;引入ISV 團隊又擔心質量和安全,培訓周期長“等等,基于此我們探索了一種新的技術體系及交付方案來解決如上問題。 ......

    uj5u.com 2023-04-20 08:18:49 more
  • 05單件模式

    #經典的單件模式 public class Singleton { private static Singleton uniqueInstance; //一個靜態變數持有Singleton類的唯一實體。 // 其他有用的實體變數寫在這里 //構造器宣告為私有,只有Singleton可以實體化這個類! ......

    uj5u.com 2023-04-19 08:42:51 more
  • 【架構與設計】常見微服務分層架構的區別和落地實踐

    軟體工程的方方面面都遵循一個最基本的道理:沒有銀彈,架構分層模型更是如此,每一種都有各自優缺點,所以請根據不同的業務場景,并遵循簡單、可演進這兩個重要的架構原則選擇合適的架構分層模型即可。 ......

    uj5u.com 2023-04-19 08:42:41 more