我們在前面的文章中已經(jīng)學(xué)習(xí)了目前開發(fā)所需的主流框架
讓客戶滿意是我們工作的目標(biāo),不斷超越客戶的期望值來自于我們對這個行業(yè)的熱愛。我們立志把好的技術(shù)通過有效、簡單的方式提供給客戶,將通過不懈努力成為客戶在信息化領(lǐng)域值得信任、有價值的長期合作伙伴,公司提供的服務(wù)項目有:申請域名、網(wǎng)站空間、營銷軟件、網(wǎng)站建設(shè)、建湖網(wǎng)站維護(hù)、網(wǎng)站推廣。
類似于我們所學(xué)習(xí)的SpringBoot框架用于簡化Spring開發(fā),我們的國人大大也開發(fā)了一款MyBatisPlus框架用來簡化MyBatis開發(fā)
下面讓我們來逐步掌握MyBatisPlus的內(nèi)容吧~
首先我們來簡單介紹一下MyBatisPlus:
MyBatisPlus開發(fā)具有三種開發(fā)方式:
我們以基于SpringBoot使用MyBatisPlus為案例來展示MyBatisPlus開發(fā)的便捷性
首先我們回憶一下SpringBoot使用MyBatis開發(fā)的相關(guān)步驟:
其中最為繁瑣的就是數(shù)據(jù)層接口的配置,需要書寫大量的@注解來進(jìn)行數(shù)據(jù)庫的查詢
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 getAll();
}
我們的SpringBoot使用MyBatisPlus大量簡化了數(shù)據(jù)層代碼書寫
我們下面依次介紹整體步驟:
4.0.0
org.springframework.boot
spring-boot-starter-parent
2.5.0
com.itheima
mybatisplus_01_quickstart
0.0.1-SNAPSHOT
1.8
com.baomidou
mybatis-plus-boot-starter
3.4.1
org.springframework.boot
spring-boot-starter
com.alibaba
druid
1.1.16
mysql
mysql-connector-java
runtime
org.springframework.boot
spring-boot-starter-test
test
org.springframework.boot
spring-boot-maven-plugin
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為了使掃描到該數(shù)據(jù)層包(SpringBoot中提及)
@Mapper
// 注意:MyBatisPlus不需要書寫方法,我們直接繼承BaseMapper類,并表明我們所使用的實體類即可
public interface UserDao extends BaseMapper {
// 不需要書寫方法,在BaseMapper類中為我們配置了大量的數(shù)據(jù)庫方法來查詢,新增,修改,刪除
}
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類,并調(diào)用其方法即可(MyBatisPlus提供方法)
// 在這里我們僅調(diào)用selectById方法,當(dāng)作測試
@Test
void testGetById(){
User user = userDao.selectById(2L);
System.out.println(user);
}
}
至此,我們的第一個MyBatisPlus案例就結(jié)束了
在使用過MyBatisPlus后,我們就可以重新介紹一下MyBatisPlus了:
MyBatisPlus特征:
最后提及一句:MyBatisPlus是由國人開發(fā),官網(wǎng)也是以中文書寫,具有中國風(fēng)范~
我們在前面已經(jīng)大致掌握了MyBatisPlus的具體操作流程,下面讓我們更加細(xì)膩的分析數(shù)據(jù)層開發(fā)
在正式開始講解數(shù)據(jù)層開發(fā)前,為大家提供一個簡單可靠的依賴:
那么這個坐標(biāo)具有什么作用呢
我們采用一個簡單的案例來展示:
org.projectlombok
lombok
1.18.12
provided
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重構(gòu)方法
@NoArgsConstructor:無參構(gòu)造
@AllArgsConstructor:有參構(gòu)造
其中我們最常用的注解是:
@Data:包括了除構(gòu)造函數(shù)外的所有方法(Set,Get,ToString,hashCode,equals)
*/
首先我們來列出一些我們通常開發(fā)中會使用的數(shù)據(jù)層語句:
功能 | MP接口 |
---|---|
新增 | int insert(T t) |
刪除 | int deleteById(Serializable id) |
修改 | int updateById(T t) |
根據(jù)id查詢 | T selectById(Serializable id) |
查詢?nèi)?/td> | List |
上述方法我們無需在數(shù)據(jù)層定義,直接測試即可:
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 {
// 自動裝配數(shù)據(jù)層
@Autowired
private UserDao userDao;
// 注意:id的數(shù)據(jù)類型為LONG,數(shù)值后需要加L
// 注意:下述部分方法需要返回id,實體類,null
// 新增
@Test
void testSave(){
User user = new User();
user.setName("黑馬程序員");
user.setPassword("itheima");
user.setAge(12);
user.setTel("");
userDao.insert(user);
}
// 刪除
@Test
void testDelete(){
userDao.deleteById(1L);
}
// 更新(注意:根據(jù)id進(jìn)行更新,更新與原數(shù)據(jù)不同的數(shù)值,null值不進(jìn)行更新)
@Test
void testUpdate(){
User user = new User();
user.setId(1L);
user.setName("Tom888");
user.setPassword("tom888");
userDao.updateById(user);
}
// 根據(jù)id查詢
@Test
void testGetById(){
User user = userDao.selectById(2L);
System.out.println(user);
}
// 查詢?nèi)? @Test
void testGetAll() {
List userList = userDao.selectList(null);
System.out.println(userList);
}
}
我們將分頁查詢單獨列為一個小節(jié)進(jìn)行講解:
功能 | MP接口 |
---|---|
分頁查詢 | IPage |
MyBatisPlus的分頁查詢需要一些前置條件,我們下面一一講述:
// MyBatisPlus的分頁操作需要添加攔截器
// 我們在Java文件夾下創(chuàng)建Config文件夾,創(chuàng)建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 {
// 需要設(shè)置為Bean
@Bean
public MybatisPlusInterceptor mpInterceptor(){
//1.定義Mp攔截器MybatisPlusInterceptor(相當(dāng)于外層攔截器)
MybatisPlusInterceptor mpInterceptor = new MybatisPlusInterceptor();
//2.添加具體的攔截器PaginationInnerInterceptor(相當(dāng)于在大攔截器中添加小攔截器)
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需要兩個參數(shù)IPage和Wrapper,IPage具有Page的實現(xiàn)類,Wrapper我們會在后續(xù)講到,這里暫設(shè)為null
//IPage對象封裝了分頁操作相關(guān)的數(shù)據(jù),第一個參數(shù)為開始數(shù),第二個數(shù)為本頁可展示數(shù)據(jù)數(shù)
IPage page = new Page(2,3);
userDao.selectPage(page,null);
// 下述為page本身攜帶的一些方法,用于查看相關(guān)數(shù)據(jù)
System.out.println("當(dāng)前頁碼值:"+page.getCurrent());
System.out.println("每頁顯示數(shù):"+page.getSize());
System.out.println("一共多少頁:"+page.getPages());
System.out.println("一共多少條數(shù)據(jù):"+page.getTotal());
System.out.println("數(shù)據(jù):"+page.getRecords());
}
}
# 如果我們想要查看實際開發(fā)的數(shù)據(jù)庫語句,我們可以選擇開啟日志進(jìn)行查看
# 查看日志方法設(shè)置在yaml配置文件中
# 開啟mp的日志(輸出到控制臺)
mybatis-plus:
configuration:
log-impl: org.apache.ibatis.logging.stdout.StdOutImpl
我們在前面已經(jīng)講解了簡單的數(shù)據(jù)層開發(fā),下面我們將會進(jìn)一步講解DQL的編程內(nèi)容
在正式開始前,我們講一些簡單輕松的知識點:
那么我們該如何清除呢
# 我們只需要將spring和MyBatisPlus的banner設(shè)置為false即可關(guān)閉版本圖
# 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類型的類來創(chuàng)造Wrapper條件判斷參數(shù)
QueryWrapper qw = new QueryWrapper();
// 我們采用QueryWrapper的一些方法來進(jìn)行給予判斷條件,后續(xù)我們會進(jìn)行介紹
// 這里采用lt小于方法,后面跟String類型字符串代表數(shù)據(jù)庫列名,在跟數(shù)值表示值
qw.lt("age",18);
// 我們采用userDao的selectList方法根據(jù)qw條件判斷機(jī)制來進(jìn)行獲取數(shù)據(jù)
// 獲取了User數(shù)值的List,并打印即可
List 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 qw = new QueryWrapper();
// MyBatisPlus可支持Lambda表達(dá)式,我們使用lambda方法使后續(xù)操作均變?yōu)長ambda表達(dá)式形式
// 我們的String數(shù)據(jù)庫列名可以采用Lambda表達(dá)式形式書寫
qw.lambda().lt(User::getAge, 10);
List 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,后續(xù)操作可以直接采用Lambda表達(dá)式,不用攜帶方法lambda
LambdaQueryWrapper lqw = new LambdaQueryWrapper();
lqw.lt(User::getAge, 10);
List userList = userDao.selectList(lqw);
System.out.println(userList);
}
}
除了上面三種基本條件查詢外,我們可以發(fā)現(xiàn)條件查詢是可以疊加使用的,主要分為兩種疊加方式:
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 lqw = new LambdaQueryWrapper();
// 依次分開書寫
lqw.lt(User::getAge, 30);
lqw.gt(User::getAge, 10);
List 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 lqw = new LambdaQueryWrapper();
// 鏈?zhǔn)蒋B加書寫
lqw.lt(User::getAge, 30).gt(User::getAge, 10);
List 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() {
//并且關(guān)系
LambdaQueryWrapper lqw = new LambdaQueryWrapper();
//并且關(guān)系:10到30歲之間(直接鏈?zhǔn)綍鴮懠纯?
lqw.lt(User::getAge, 30).gt(User::getAge, 10);
List 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() {
//或者關(guān)系
LambdaQueryWrapper lqw = new LambdaQueryWrapper();
//或者關(guān)系:小于10歲或者大于30歲(在條件之間采用or方法來隔離)
lqw.lt(User::getAge, 10).or().gt(User::getAge, 30);
List userList = userDao.selectList(lqw);
System.out.println(userList);
}
}
我們在做實際項目處理時,會出現(xiàn)各種查詢框架
例如價格查詢搜索產(chǎn)品,但我們可能不會同時給出最低價限制和最高價限制
我們以代碼來做一個簡單示例:
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() {
// 模擬頁面?zhèn)鬟f過來的查詢數(shù)據(jù)
UserQuery uq = new UserQuery();
// 如果我們下面的數(shù)據(jù)有一個沒有設(shè)置,就會導(dǎo)致查詢語句中的?沒有填充,導(dǎo)致搜索失敗
uq.setAge(10);
uq.setAge2(null);
// null判定
LambdaQueryWrapper lqw = new LambdaQueryWrapper();
lqw.lt(User::getAge, uq.getAge2());
lqw.gt(User::getAge, uq.getAge());
List userList = userDao.selectList(lqw);
System.out.println(userList)
}
}
在之前我們的null值處理大部分都是采用if語句來進(jìn)行判斷:
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() {
// 模擬頁面?zhèn)鬟f過來的查詢數(shù)據(jù)
UserQuery uq = new UserQuery();
// 可能出現(xiàn)有任意一個數(shù)沒有賦值
uq.setAge(10);
uq.setAge2(null);
// null判定
LambdaQueryWrapper lqw = new LambdaQueryWrapper();
lqw.lt(User::getAge, uq.getAge2());
// 正常我們采用if來進(jìn)行判斷是否有值,若有值則加入操作
// 但當(dāng)if語句過多,導(dǎo)致代碼冗雜
if( null != uq.getAge()) {
lqw.gt(User::getAge, uq.getAge());
}
List 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() {
// 模擬頁面?zhèn)鬟f過來的查詢數(shù)據(jù)
UserQuery uq = new UserQuery();
uq.setAge(10);
uq.setAge2(30);
// LambdaQueryWrapper的各種方法中均攜帶了一個判定條件在最前面的參數(shù)中,當(dāng)成立執(zhí)行后續(xù)操作,不成立直接跳過
LambdaQueryWrapper lqw = new LambdaQueryWrapper();
// 先判定第一個參數(shù)是否為true,如果為true連接當(dāng)前條件
lqw.lt(null != uq.getAge2(),User::getAge, uq.getAge2());
lqw.gt(null != uq.getAge(),User::getAge, uq.getAge());
List userList = userDao.selectList(lqw);
System.out.println(userList);
}
}
我們選擇性的查詢數(shù)據(jù)庫列稱為查詢投影,接下來讓我們來介紹查詢投影的實現(xiàn)方法
查詢投影的實現(xiàn)我們大致分為兩種類型:
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() {
// 查詢投影
// 當(dāng)我們所查詢的內(nèi)容屬于實體類中包含的屬性,我們可以采用QW或LambdaQW來實現(xiàn)
// 我們大部分采用LambdaQW來實現(xiàn),因為帶有自動識別,不易出錯
LambdaQueryWrapper lqw = new LambdaQueryWrapper();
// 我們采用select方法來添加查詢種類,LambdaQueryWrapper采用Lambda表達(dá)式添加
lqw.select(User::getId,User::getName,User::getAge);
QueryWrapper lqw = new QueryWrapper();
// 我們采用select方法來添加查詢種類,QueryWrapper采用String添加
lqw.select("id","name","age","tel");
List 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 lqw = new QueryWrapper();
lqw.select("count(*) as count, tel");
// QueryWrapper提供了分組方法groupBy,參數(shù)為String類型的數(shù)據(jù)庫列名
lqw.groupBy("tel");
List
首先我們給出所有查詢條件官網(wǎng)鏈接:條件構(gòu)造器 | MyBatis-Plus (baomidou.com)
如果有需要可以上網(wǎng)查詢相關(guān)構(gòu)造方法
下面我們僅對一些常用查詢條件進(jìn)行展示:
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 lqw = new LambdaQueryWrapper();
// eq等同于=
lqw.eq(User::getName,"Jerry").eq(User::getPassword,"jerry");
User loginUser = userDao.selectOne(lqw);
System.out.println(loginUser);
LambdaQueryWrapper lqw = new LambdaQueryWrapper();
//范圍查詢 lt le gt ge eq between
lqw.between(User::getAge,10,30);
List userList = userDao.selectList(lqw);
System.out.println(userList);
LambdaQueryWrapper lqw = new LambdaQueryWrapper();
//模糊匹配 like
lqw.likeLeft(User::getName,"J");
List userList = userDao.selectList(lqw);
System.out.println(userList);
// 查詢?nèi)? LambdaQueryWrapper lqw = new LambdaQueryWrapper();
List userList = userDao.selectList(lqw);
System.out.println(userList);
}
}
最后介紹的依舊是我們在MyBatis中也出現(xiàn)的老問題:
我們在下面分為幾種情況來講解:
// 假設(shè)我們的數(shù)據(jù)庫表名為tbl_user,但我們的實體類設(shè)計為User
package com.itheima.domain;
import com.baomidou.mybatisplus.annotation.TableField;
import com.baomidou.mybatisplus.annotation.TableName;
import lombok.Data;
// 采用注解@TableName,后面跟對應(yīng)的數(shù)據(jù)庫表名
@TableName("tbl_user")
public class User {
private Long id;
private String name;
private String password;
private Integer age;
private String tel;
}
// 假設(shè)我們的數(shù)據(jù)庫密碼設(shè)計為pwd,但是我們的實體類密碼屬性設(shè)計為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=數(shù)據(jù)庫列名
@TableField(value = "pwd")
private String password;
private Integer age;
private String tel;
}
// 例如我們的pwd密碼,在查詢時不應(yīng)當(dāng)被查詢,但是我們采用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設(shè)置為false,即為不可查詢
@TableField(value = "pwd",select = false)
private String password;
private Integer age;
private String tel;
}
// 例如我們設(shè)計了一個屬性online判斷是否在線,不用放于數(shù)據(jù)庫中,我們該如何在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設(shè)置為false,則判斷該屬性不存在于數(shù)據(jù)庫中
@TableField(exist = false)
private Integer online;
}
我們將上述內(nèi)容分離出來主要解釋兩個注解:
這一章節(jié)我們來講一些MyBatisPlus中經(jīng)常用到的操作,下面我們一一介紹
我們在實際開發(fā)中會有需要ID生成需求,對于不同的情況需要采取不同的ID生成方法:
因此MyBatisPlus提供了一種新的注解來實現(xiàn)這類需求:
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
//設(shè)置表名映射關(guān)系
@TableName("tbl_user")
public class User {
//設(shè)置主鍵生成策略(這里設(shè)置為自增)
@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;
}
我們也可以同一設(shè)置@TableId的type屬性,使整個項目的@TableId都以一種形態(tài)執(zhí)行:
# 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 # 設(shè)置為雪花算法設(shè)置ID
我們在實際開發(fā)中常常會進(jìn)行多條記錄操作:
MyBatisPlus也為我們提供了相對應(yīng)的方法:
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(){
//刪除指定多條數(shù)據(jù)
//deleteBatchIds參數(shù)為數(shù)組形式,我們提供id的數(shù)組即可
List list = new ArrayList<>();
list.add(L);
list.add(L);
list.add(L);
userDao.deleteBatchIds(list);
}
@Test
void testSelect()}{
//查詢指定多條數(shù)據(jù)
//selectBatchIds參數(shù)為數(shù)組形式,我們提供id的數(shù)組即可
List list = new ArrayList<>();
list.add(1L);
list.add(3L);
list.add(4L);
userDao.selectBatchIds(list);
}
}
我們在實際開發(fā)中面對項目的刪除操作有時并非是真正的刪除操作:
因而我們提出了邏輯刪除的概念:
下面我們來講解如何在MyBatisPlus中實現(xiàn)這種思想:
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
//設(shè)置表名映射關(guān)系
@TableName("tbl_user")
public class User {
//設(shè)置主鍵生成策略
@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;
//邏輯刪除字段,標(biāo)記當(dāng)前記錄是否被刪除(value原值,delval修改值)
@TableLogic(value = "0" ,delval = "1")
private Integer deleted;
}
/*
@TableLogic
在設(shè)置之后,我們采用delete方法時,不會直接刪除數(shù)據(jù),而是將該數(shù)據(jù)值從value變?yōu)閐elval
類似于:UPDATE tbl_user SET deleted = 1 WHERE id = ? AND deleted = 0;
*/
同樣,我們的邏輯刪除值也可以進(jìn)行統(tǒng)一設(shè)置:
# 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
我們在業(yè)務(wù)開發(fā)中也會遇到多線程的問題:
首先我們來講解一下樂觀鎖的基本概念:
在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
//設(shè)置表名映射關(guān)系
@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;
}
/*
我們來講解一下為什么需要使用攔截器
我們將前面我們介紹的樂觀鎖概念轉(zhuǎn)化為語句:
SELETE version FROM tbl_user
UPDATE tbl_user SET ...(用戶修改) version=version+1 WHERE id = ? AND version = version(我們之前讀取的version)
倘若用戶操作前有其他用戶操作,那么version就會發(fā)生變化,導(dǎo)致用戶無法找到對應(yīng)的數(shù)據(jù),無法操作
因為我們需要對前面的version進(jìn)行修改,我們需要將語句攔截下來進(jìn)行一定修改,所以這里采用攔截器
*/
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(){
// 我們設(shè)置一個實例User,id為1,version為1
User user = new User();
user.setId(1L);
user.setName("Jock666");
user.setVersion(1);
userDao.updateById(user);
// 我們用user,user2來當(dāng)作兩個用戶
// 假設(shè)兩個用戶同時讀取數(shù)據(jù)
User user = userDao.selectById(3L); //version=1
User user2 = userDao.selectById(3L); //version=1
// user用戶首先進(jìn)行操作(這時 實例version為1 操作成立 ,操作結(jié)束后version變?yōu)?)
// UPDATE tbl_user SET ...(用戶修改) version=2 WHERE id = 1 AND version = 1
user.setName("Jock aaa");
userDao.updateById(user2);
// user2用戶開始操作(這時 實例version為2 但前面讀取的version為1,讀取不到數(shù)據(jù),無法操作)
// UPDATE tbl_user SET ...(用戶修改) version=2 WHERE id = 1 AND version = 1(已讀取不到數(shù)據(jù))
user2.setName("Jock bbb");
userDao.updateById(user);
}
}
好的,關(guān)于MyBatisPlus的內(nèi)容就介紹到這里,希望能為你帶來幫助!
該文章屬于學(xué)習(xí)內(nèi)容,具體參考B站黑馬程序員李老師的SSM框架課程
這里附上鏈接:MyBatisPlus-01-MybatisPlus入門案例_嗶哩嗶哩_bilibili