我們在前面的文章中已經學習了目前開發所需的主流框架
類似於我們所學習的SpringBoot框架用於簡化Spring開發,我們的國人大大也開發了一款MyBatisPlus框架用來簡化MyBatis開發
下面讓我們來逐步掌握MyBatisPlus的內容吧~
首先我們來簡單介紹一下MyBatisPlus:
MyBatisPlus開發具有三種開發方式:
我們以基於SpringBoot使用MyBatisPlus為案例來展示MyBatisPlus開發的便捷性
首先我們回憶一下SpringBoot使用MyBatis開發的相關步驟:
其中最為繁瑣的就是資料層介面的設定,需要書寫大量的@註解來進行資料庫的查詢
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大量簡化了資料層程式碼書寫
我們下面依次介紹整體步驟:
<?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>
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
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 + '\'' +
'}';
}
}
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類中為我們設定了大量的資料庫方法來查詢,新增,修改,刪除
}
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是由國人開發,官網也是以中文書寫,具有中國風範~
我們在前面已經大致掌握了MyBatisPlus的具體操作流程,下面讓我們更加細膩的分析資料層開發
在正式開始講解資料層開發前,為大家提供一個簡單可靠的依賴:
那麼這個座標具有什麼作用呢
我們採用一個簡單的案例來展示:
<dependency>
<groupId>org.projectlombok</groupId>
<artifactId>lombok</artifactId>
<version>1.18.12</version>
<scope>provided</scope>
</dependency>
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 |
上述方法我們無需在資料層定義,直接測試即可:
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的分頁查詢需要一些前置條件,我們下面一一講述:
// 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;
}
}
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());
}
}
# 如果我們想要檢視實際開發的資料庫語句,我們可以選擇開啟紀錄檔進行檢視
# 檢視紀錄檔方法設定在yaml組態檔中
# 開啟mp的紀錄檔(輸出到控制檯)
mybatis-plus:
configuration:
log-impl: org.apache.ibatis.logging.stdout.StdOutImpl
我們在前面已經講解了簡單的資料層開發,下面我們將會進一步講解DQL的程式設計內容
在正式開始前,我們講一些簡單輕鬆的知識點:
那麼我們該如何清除呢
<!--我們在sources中新創一個spring config 檔案-->
<!--設定一個configuration雙標籤,不用填寫內容即可-->
<?xml version="1.0" encoding="UTF-8"?>
<configuration>
</configuration>
# 我們只需要將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:
接下來我們就來介紹三種基本條件查詢:
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);
}
}
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);
}
}
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);
}
}
除了上面三種基本條件查詢外,我們可以發現條件查詢是可以疊加使用的,主要分為兩種疊加方式:
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);
}
}
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);
}
}
最後我們還要介紹兩種組合查詢條件形式:
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);
}
}
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);
}
}
我們選擇性的查詢資料庫列稱為查詢投影,接下來讓我們來介紹查詢投影的實現方法
查詢投影的實現我們大致分為兩種型別:
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);
}
}
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中也出現的老問題:
我們在下面分為幾種情況來講解:
// 假設我們的資料庫表名為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;
}
// 假設我們的資料庫密碼設計為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=資料庫列名
@TableField(value = "pwd")
private String password;
private Integer age;
private String tel;
}
// 例如我們的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 = "pwd",select = false)
private String password;
private Integer age;
private String tel;
}
// 例如我們設計了一個屬性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 = "pwd",select = false)
private String password;
private Integer age;
private String tel;
// 採用@TableField註解,後面跟屬性exist設定為false,則判斷該屬性不存在於資料庫中
@TableField(exist = false)
private Integer online;
}
我們將上述內容分離出來主要解釋兩個註解:
這一章節我們來講一些MyBatisPlus中經常用到的操作,下面我們一一介紹
我們在實際開發中會有需要ID生成需求,對於不同的情況需要採取不同的ID生成方法:
因此MyBatisPlus提供了一種新的註解來實現這類需求:
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 = "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);
}
}
我們在實際開發中面對專案的刪除操作有時並非是真正的刪除操作:
因而我們提出了邏輯刪除的概念:
下面我們來講解如何在MyBatisPlus中實現這種思想:
ALTER TABLE tb_user ADD deleted int(1) DEFAULT 0;
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 = "pwd",select = false)
private String password;
private Integer age;
private String tel;
@TableField(exist = false)
private Integer online;
//邏輯刪除欄位,標記當前記錄是否被刪除(value原值,delval修改值)
@TableLogic(value = "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
我們在業務開發中也會遇到多執行緒的問題:
首先我們來講解一下樂觀鎖的基本概念:
在MyBatisPlus中我們採用樂觀鎖的概念來解決:
ALTER TABLE tb_user ADD version int(11) DEFAULT 1;
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 = "pwd",select = false)
private String password;
private Integer age;
private String tel;
@TableField(exist = false)
private Integer online;
@TableLogic(value = "0" ,delval = "1")
private Integer deleted;
// version版本註解(樂觀鎖)
@Version
private Integer version;
}
/*
我們來講解一下為什麼需要使用攔截器
我們將前面我們介紹的樂觀鎖概念轉化為語句:
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;
}
}
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