一 MyBatisPlus簡(jiǎn)介
1. 入門案例
問(wèn)題導(dǎo)入
MyBatisPlus環(huán)境搭建的步驟?
1.1 SpringBoot整合MyBatisPlus入門程序
①:創(chuàng)建新模塊,選擇Spring初始化,并配置模塊相關(guān)基礎(chǔ)信息
②:選擇當(dāng)前模塊需要使用的技術(shù)集(僅保留JDBC)
③:手動(dòng)添加MyBatisPlus起步依賴
<dependency>
<groupId>com.baomidou</groupId>
<artifactId>mybatis-plus-boot-starter</artifactId>
<version>3.5.2</version>
</dependency>
<dependency>
<groupId>com.alibaba</groupId>
<artifactId>druid</artifactId>
<version>1.2.8</version>
</dependency>
注意事項(xiàng)1:由于mp并未被收錄到idea的系統(tǒng)內(nèi)置配置,無(wú)法直接選擇加入
注意事項(xiàng)2:如果使用Druid數(shù)據(jù)源,需要導(dǎo)入對(duì)應(yīng)坐標(biāo)
④:制作實(shí)體類與表結(jié)構(gòu)
(類名與表名對(duì)應(yīng),屬性名與字段名對(duì)應(yīng))
create database if not exists mybatisplus_db character set utf8;
use mybatisplus_db;
CREATE TABLE user (
id bigint(20) primary key auto_increment,
name varchar(32) not null,
password varchar(32) not null,
age int(3) not null ,
tel varchar(32) not null
);
insert into user values(null,'tom','123456',12,'12345678910');
insert into user values(null,'jack','123456',8,'12345678910');
insert into user values(null,'jerry','123456',15,'12345678910');
insert into user values(null,'tom','123456',9,'12345678910');
insert into user values(null,'snake','123456',28,'12345678910');
insert into user values(null,'張益達(dá)','123456',22,'12345678910');
insert into user values(null,'張大炮','123456',16,'12345678910');
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;
}
@Override
public String toString() {
return "User{" +
"id=" + id +
", name='" + name + '\'' +
", password='" + password + '\'' +
", age=" + age +
", tel='" + tel + '\'' +
'}';
}
}
⑤:設(shè)置Jdbc參數(shù)(application.yml)
spring:
datasource:
type: com.alibaba.druid.pool.DruidDataSource
driver-class-name: com.mysql.cj.jdbc.Driver
url: jdbc:mysql://localhost:3306/mybatisplus_db?characterEncoding=utf8&useSSL=false&serverTimezone=Asia/Shanghai&rewriteBatchedStatements=true
username: root
password: root
⑥:定義數(shù)據(jù)接口,繼承BaseMapper
package com.itheima.dao;
import com.baomidou.mybatisplus.core.mapper.BaseMapper;
import com.itheima.domain.User;
import org.apache.ibatis.annotations.Mapper;
@Mapper
public interface UserDao extends BaseMapper<User> {
}
⑦:測(cè)試類中注入dao接口,測(cè)試功能
package com.itheima;
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
public class Mybatisplus01QuickstartApplicationTests {
@Autowired
private UserDao userDao;
@Test
void testGetAll() {
List<User> userList = userDao.selectList(null);
System.out.println(userList);
}
}
2. MyBatisPlus概述
問(wèn)題導(dǎo)入
通過(guò)入門案例制作,MyBatisPlus的優(yōu)點(diǎn)有哪些?
2.1 MyBatis介紹
- MyBatisPlus(簡(jiǎn)稱MP)是基于MyBatis框架基礎(chǔ)上開發(fā)的增強(qiáng)型工具,旨在簡(jiǎn)化開發(fā)、提高效率
- 官網(wǎng):
- https://mybatis.plus/
- https://mp.baomidou.com/
- 無(wú)侵入:只做增強(qiáng)不做改變,不會(huì)對(duì)現(xiàn)有工程產(chǎn)生影響
- 強(qiáng)大的 CRUD 操作:內(nèi)置通用 Mapper,少量配置即可實(shí)現(xiàn)單表CRUD 操作
- 支持 Lambda:編寫查詢條件無(wú)需擔(dān)心字段寫錯(cuò)
- 支持主鍵自動(dòng)生成
- 內(nèi)置分頁(yè)插件
- ……
二 標(biāo)準(zhǔn)數(shù)據(jù)層開發(fā)
1. MyBatisPlus的CRUD操作
package com.itheima;
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 testSave() {
User user = new User();
user.setName("黑馬程序員");
user.setPassword("itheima");
user.setAge(12);
user.setTel("4006184000");
userDao.insert(user);
}
@Test
void testDelete() {
userDao.deleteById(1401856123725713409L);
}
@Test
void testUpdate() {
User user = new User();
user.setId(1L);
user.setName("Tom888");
user.setPassword("tom888");
userDao.updateById(user);
}
@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);
}
}
2. Lombok插件介紹
問(wèn)題導(dǎo)入
有什么簡(jiǎn)單的辦法可以自動(dòng)生成實(shí)體類的GET、SET方法?
- Lombok,一個(gè)Java類庫(kù),提供了一組注解,簡(jiǎn)化POJO實(shí)體類開發(fā)。
<dependency>
<groupId>org.projectlombok</groupId>
<artifactId>lombok</artifactId>
<version>1.18.24</version>
</dependency>
- 常用注解:@Data,為當(dāng)前實(shí)體類在編譯期設(shè)置對(duì)應(yīng)的get/set方法,無(wú)參/無(wú)參構(gòu)造方法,toString方法,hashCode方法,equals方法等
package com.itheima.domain;
import lombok.*;
/*
1 生成getter和setter方法:@Getter、@Setter
生成toString方法:@ToString
生成equals和hashcode方法:@EqualsAndHashCode
2 統(tǒng)一成以上所有:@Data
3 生成空參構(gòu)造: @NoArgsConstructor
生成全參構(gòu)造: @AllArgsConstructor
4 lombok還給我們提供了builder的方式創(chuàng)建對(duì)象,好處就是可以鏈?zhǔn)骄幊獭?@Builder【擴(kuò)展】
*/
@Data
public class User {
private Long id;
private String name;
private String password;
private Integer age;
private String tel;
}
2.1 @Getter和@Setter
@Getter和@Setter是Lombok中最常用的注解之一,它們用于自動(dòng)生成Java Bean類的Getters和Setters方法。使用這兩個(gè)注解可以減少代碼量,提高代碼的可讀性和可維護(hù)性。
使用方式:
import lombok.Getter;
import lombok.Setter;
@Getter
@Setter
public class User {
private String name;
private int age;
}
注解的作用:
在上面的代碼中,我們使用了@Getter和@Setter注解來(lái)自動(dòng)生成User類的Getters和Setters方法,這樣我們就可以通過(guò)下列代碼來(lái)訪問(wèn)User類的屬性:
User user = new User();
user.setName("Tom");
user.setAge(20);
System.out.println(user.getName());
System.out.println(user.getAge());
2.2 @ToString
@ToString注解可以自動(dòng)生成toString方法。這個(gè)方法可以將一個(gè)對(duì)象的屬性轉(zhuǎn)換成一個(gè)字符串,方便輸出調(diào)試信息。
使用方式:
import lombok.ToString;
@ToString
public class User {
private String name;
private int age;
}
注解的作用:
在上面的代碼中,我們使用了@ToString注解來(lái)自動(dòng)生成User類的toString方法,這樣我們就可以通過(guò)下列代碼來(lái)輸出User對(duì)象的屬性:
User user = new User();
user.setName("Tom");
user.setAge(20);
System.out.println(user);
輸出結(jié)果為:
User(name=Tom, age=20)
2.3 @EqualsAndHashCode
@EqualsAndHashCode注解可以自動(dòng)生成equals和hashCode方法。這個(gè)方法可以用來(lái)比較兩個(gè)對(duì)象是否相等。
使用方式:
import lombok.EqualsAndHashCode;
@EqualsAndHashCode
public class User {
private String name;
private int age;
}
注解的作用:
在上面的代碼中,我們使用了@EqualsAndHashCode注解來(lái)自動(dòng)生成User類的equals和hashCode方法,這樣我們就可以通過(guò)下列代碼來(lái)比較兩個(gè)User對(duì)象是否相等:
User user1 = new User();
user1.setName("Tom");
user1.setAge(20);
User user2 = new User();
user2.setName("Tom");
user2.setAge(20);
System.out.println(user1.equals(user2));
輸出結(jié)果為:
true
2.4 @NoArgsConstructor和@AllArgsConstructor
@NoArgsConstructor和@AllArgsConstructor注解可以自動(dòng)生成無(wú)參構(gòu)造方法和全參構(gòu)造方法。
使用方式:
import lombok.AllArgsConstructor;
import lombok.NoArgsConstructor;
@NoArgsConstructor
@AllArgsConstructor
public class User {
private String name;
private int age;
}
注解的作用:
在上面的代碼中,我們使用了@NoArgsConstructor和@AllArgsConstructor注解來(lái)自動(dòng)生成User類的無(wú)參構(gòu)造方法和全參構(gòu)造方法,這樣我們就可以通過(guò)下列代碼來(lái)創(chuàng)建User對(duì)象:
User user1 = new User();
User user2 = new User("Tom", 20);
2.5 @Data
@Data注解可以自動(dòng)生成Getter、Setter、equals、hashCode和toString方法,相當(dāng)于同時(shí)使用了@Getter、@Setter、@EqualsAndHashCode和@ToString注解。
使用方式:
import lombok.Data;
@Data
public class User {
private String name;
private int age;
}
注解的作用:
在上面的代碼中,我們使用了@Data注解來(lái)自動(dòng)生成User類的Getter、Setter、equals、hashCode和toString方法,這樣我們就可以通過(guò)下列代碼來(lái)訪問(wèn)User類的屬性、比較兩個(gè)User對(duì)象是否相等以及輸出User對(duì)象的屬性:
User user1 = new User();
user1.setName("Tom");
user1.setAge(20);
User user2 = new User();
user2.setName("Tom");
user2.setAge(20);
System.out.println(user1.equals(user2));
System.out.println(user1.toString());
輸出結(jié)果為:
true
User(name=Tom, age=20)
2.6 @Builder
@Builder注解可以自動(dòng)生成Builder模式的代碼。Builder模式是一種創(chuàng)建對(duì)象的設(shè)計(jì)模式,它可以讓我們更加靈活地創(chuàng)建對(duì)象,同時(shí)也可以提高代碼的可讀性和可維護(hù)性。
使用方式:
import lombok.Builder;
@Builder
public class User {
private String name;
private int age;
}
注解的作用:
在上面的代碼中,我們使用了@Builder注解來(lái)自動(dòng)生成User類的Builder模式的代碼,這樣我們就可以通過(guò)下列代碼來(lái)創(chuàng)建User對(duì)象:
User user = User.builder()
.name("Tom")
.age(20)
.build();
2.7 @Slf4j
@Slf4j注解可以自動(dòng)生成日志記錄代碼。日志記錄是一種常用的調(diào)試和錯(cuò)誤處理方法,它可以幫助我們更好地了解程序的運(yùn)行情況。
使用方式:
import lombok.extern.slf4j.Slf4j;
@Slf4j
public class User {
private String name;
private int age;
public void hello() {
log.info("Hello, {}!", name);
}
}
注解的作用:
在上面的代碼中,我們使用了@Slf4j注解來(lái)自動(dòng)生成User類的日志記錄代碼,這樣我們就可以通過(guò)下列代碼來(lái)記錄User對(duì)象的hello方法的調(diào)用情況:
User user = new User();
user.setName("Tom");
user.hello();
輸出結(jié)果為:
INFO User:9 - Hello, Tom!
總結(jié)
Lombok是一個(gè)非常實(shí)用的Java庫(kù),它可以幫助我們簡(jiǎn)化Java代碼的編寫,減少樣板代碼的重復(fù),提高代碼的可讀性和可維護(hù)性。本文介紹了Lombok中常用的注解及其用法,包括@Getter、@Setter、@ToString、@EqualsAndHashCode、@NoArgsConstructor、@AllArgsConstructor、@Data、@Builder和@Slf4j。通過(guò)學(xué)習(xí)這些注解,我們可以更加高效地編寫Java代碼。
3. MyBatisPlus分頁(yè)功能
問(wèn)題導(dǎo)入
思考一下Mybatis分頁(yè)插件是如何用的?
3.1 分頁(yè)功能接口
3.2 MyBatisPlus分頁(yè)使用
①:設(shè)置分頁(yè)攔截器作為Spring管理的bean
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;
@Configuration
public class MybatisPlusConfig {
@Bean
public MybatisPlusInterceptor mpInterceptor(){
//1 創(chuàng)建MybatisPlusInterceptor攔截器對(duì)象
MybatisPlusInterceptor mpInterceptor = new MybatisPlusInterceptor();
//2 添加分頁(yè)攔截器
mpInterceptor.addInnerInterceptor(new PaginationInnerInterceptor());
return mpInterceptor;
}
}
②:執(zhí)行分頁(yè)查詢
//分頁(yè)查詢
@Test
void testSelectPage(){
//1 創(chuàng)建IPage分頁(yè)對(duì)象,設(shè)置分頁(yè)參數(shù)
IPage<User> page=new Page<>(1,3);
//2 執(zhí)行分頁(yè)查詢
userDao.selectPage(page,null);
//3 獲取分頁(yè)結(jié)果
System.out.println("當(dāng)前頁(yè)碼值:"+page.getCurrent());
System.out.println("每頁(yè)顯示數(shù):"+page.getSize());
System.out.println("總頁(yè)數(shù):"+page.getPages());
System.out.println("總條數(shù):"+page.getTotal());
System.out.println("當(dāng)前頁(yè)數(shù)據(jù):"+page.getRecords());
}
3.3 開啟MyBatisPlus日志
spring:
datasource:
type: com.alibaba.druid.pool.DruidDataSource
driver-class-name: com.mysql.cj.jdbc.Driver
url: jdbc:mysql://localhost:3306/mybatisplus_db?characterEncoding=utf8&useSSL=false&serverTimezone=Asia/Shanghai&rewriteBatchedStatements=true
username: root
password: root
# 開啟mp的日志(輸出到控制臺(tái))
mybatis-plus:
configuration:
log-impl: org.apache.ibatis.logging.stdout.StdOutImpl
3.4 解決日志打印過(guò)多問(wèn)題
3.4.1 取消初始化spring日志打印
做法: 在resources下新建一個(gè)logback.xml文件,名稱固定,內(nèi)容如下:
<?xml version="1.0" encoding="UTF-8"?>
<configuration>
</configuration>
關(guān)于logback參考播客:https://www.jianshu.com/p/75f9d11ae011
3.4.2 取消SpringBoot啟動(dòng)banner圖標(biāo)
spring:
main:
banner-mode: off # 關(guān)閉SpringBoot啟動(dòng)圖標(biāo)(banner)
3.4.3 取消MybatisPlus啟動(dòng)banner圖標(biāo)
# mybatis-plus日志控制臺(tái)輸出
mybatis-plus:
configuration:
log-impl: org.apache.ibatis.logging.stdout.StdOutImpl
global-config:
banner: off # 關(guān)閉mybatisplus啟動(dòng)圖標(biāo)
三 DQL編程控制(查)
1. 條件查詢方式
- MyBatisPlus將書寫復(fù)雜的SQL查詢條件進(jìn)行了封裝,使用編程的形式完成查詢條件的組合
1.1 條件查詢
1.1.1 方式一:按條件查詢
//方式一:按條件查詢
QueryWrapper<User> qw=new QueryWrapper<>();
qw.lt("age", 18);
List<User> userList = userDao.selectList(qw);
System.out.println(userList);
1.1.2 方式二:lambda格式按條件查詢
//方式二:lambda格式按條件查詢
QueryWrapper<User> qw = new QueryWrapper<User>();
qw.lambda().lt(User::getAge, 10);
List<User> userList = userDao.selectList(qw);
System.out.println(userList);
1.1.3 方式三:lambda格式按條件查詢(推薦)
//方式三:lambda格式按條件查詢
LambdaQueryWrapper<User> lqw = new LambdaQueryWrapper<User>();
lqw.lt(User::getAge, 10);
List<User> userList = userDao.selectList(lqw);
System.out.println(userList);
1.2 組合條件
1.2.1 并且關(guān)系(and)
//并且關(guān)系 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.2.2 或者關(guān)系(or)
//或者關(guān)系 小于10歲或者大于30歲
LambdaQueryWrapper<User> lqw = new LambdaQueryWrapper<User>();
lqw.lt(User::getAge, 10).or().gt(User::getAge, 30);
List<User> userList = userDao.selectList(lqw);
System.out.println(userList);
1.3 NULL值處理
問(wèn)題導(dǎo)入
如下搜索場(chǎng)景,在多條件查詢中,有條件的值為空應(yīng)該怎么解決?
1.3.1 if語(yǔ)句控制條件追加
Integer minAge=10; //將來(lái)有用戶傳遞進(jìn)來(lái),此處簡(jiǎn)化成直接定義變量了
Integer maxAge=null; //將來(lái)有用戶傳遞進(jìn)來(lái),此處簡(jiǎn)化成直接定義變量了
LambdaQueryWrapper<User> lqw = new LambdaQueryWrapper<User>();
if(minAge!=null){
lqw.gt(User::getAge, minAge);
}
if(maxAge!=null){
lqw.lt(User::getAge, maxAge);
}
List<User> userList = userDao.selectList(lqw);
userList.forEach(System.out::println);
1.3.2 條件參數(shù)控制
Integer minAge=10; //將來(lái)有用戶傳遞進(jìn)來(lái),此處簡(jiǎn)化成直接定義變量了
Integer maxAge=null; //將來(lái)有用戶傳遞進(jìn)來(lái),此處簡(jiǎn)化成直接定義變量了
LambdaQueryWrapper<User> lqw = new LambdaQueryWrapper<User>();
//參數(shù)1:如果表達(dá)式為true,那么查詢才使用該條件
lqw.gt(minAge!=null,User::getAge, minAge);
lqw.lt(maxAge!=null,User::getAge, maxAge);
List<User> userList = userDao.selectList(lqw);
userList.forEach(System.out::println);
1.3.3 條件參數(shù)控制(鏈?zhǔn)骄幊蹋?/h5>
Integer minAge=10; //將來(lái)有用戶傳遞進(jìn)來(lái),此處簡(jiǎn)化成直接定義變量了
Integer maxAge=null; //將來(lái)有用戶傳遞進(jìn)來(lái),此處簡(jiǎn)化成直接定義變量了
LambdaQueryWrapper<User> lqw = new LambdaQueryWrapper<User>();
//參數(shù)1:如果表達(dá)式為true,那么查詢才使用該條件
lqw.gt(minAge!=null,User::getAge, minAge)
.lt(maxAge!=null,User::getAge, maxAge);
List<User> userList = userDao.selectList(lqw);
userList.forEach(System.out::println);
2. 查詢投影-設(shè)置【查詢字段、分組、分頁(yè)】
2.1 查詢結(jié)果包含模型類中部分屬性
//使用Lambda表達(dá)式寫法
LambdaQueryWrapper<User> lqw = new LambdaQueryWrapper<User>();
lqw.select(User::getId,User::getName,User::getAge);
List<User> userList = userDao.selectList(lqw);
System.out.println(userList);
//不適用Lambda表達(dá)式寫法
QueryWrapper<User> lqw = new QueryWrapper<User>();
lqw.select("id","name","age","tel");
List<User> userList = userDao.selectList(lqw);
System.out.println(userList);
2.2 查詢結(jié)果包含模型類中未定義的屬性
QueryWrapper<User> lqw = new QueryWrapper<User>();
lqw.select("count(*) as count, tel");
lqw.groupBy("tel");
List<Map<String, Object>> userList = userDao.selectMaps(lqw);
System.out.println(userList);
3. 查詢條件設(shè)定
問(wèn)題導(dǎo)入
Integer minAge=10; //將來(lái)有用戶傳遞進(jìn)來(lái),此處簡(jiǎn)化成直接定義變量了
Integer maxAge=null; //將來(lái)有用戶傳遞進(jìn)來(lái),此處簡(jiǎn)化成直接定義變量了
LambdaQueryWrapper<User> lqw = new LambdaQueryWrapper<User>();
//參數(shù)1:如果表達(dá)式為true,那么查詢才使用該條件
lqw.gt(minAge!=null,User::getAge, minAge)
.lt(maxAge!=null,User::getAge, maxAge);
List<User> userList = userDao.selectList(lqw);
userList.forEach(System.out::println);
//使用Lambda表達(dá)式寫法
LambdaQueryWrapper<User> lqw = new LambdaQueryWrapper<User>();
lqw.select(User::getId,User::getName,User::getAge);
List<User> userList = userDao.selectList(lqw);
System.out.println(userList);
//不適用Lambda表達(dá)式寫法
QueryWrapper<User> lqw = new QueryWrapper<User>();
lqw.select("id","name","age","tel");
List<User> userList = userDao.selectList(lqw);
System.out.println(userList);
QueryWrapper<User> lqw = new QueryWrapper<User>();
lqw.select("count(*) as count, tel");
lqw.groupBy("tel");
List<Map<String, Object>> userList = userDao.selectMaps(lqw);
System.out.println(userList);
多條件查詢有哪些組合?
- 范圍匹配(> 、 = 、between)
- 模糊匹配(like)
- 空判定(null)
- 包含性匹配(in)
- 分組(group)
- 排序(order)
- ……
3.1 查詢條件
- 用戶登錄(eq匹配)
LambdaQueryWrapper<User> lqw = new LambdaQueryWrapper<User>();
//eq等同于=
lqw.eq(User::getName, "Jerry").eq(User::getPassword, 123456);
User loginUser = userDao.selectOne(lqw);
System.out.println(loginUser);
- 購(gòu)物設(shè)定價(jià)格區(qū)間、戶籍設(shè)定年齡區(qū)間(le ge匹配 或 between匹配)
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);
- 查信息,搜索新聞(非全文檢索版:like匹配)
LambdaQueryWrapper<User> lqw = new LambdaQueryWrapper<User>();
//模糊匹配 like likeLeft相當(dāng)于百分號(hào)加在左邊,right即加在右邊
lqw.likeLeft(User::getName, "J");
List<User> userList = userDao.selectList(lqw);
System.out.println(userList);
- 統(tǒng)計(jì)報(bào)表(分組查詢聚合函數(shù))
QueryWrapper<User> qw = new QueryWrapper<User>();
qw.select("gender","count(*) as nums");
qw.groupBy("gender");
List<Map<String, Object>> maps = userDao.selectMaps(qw);
System.out.println(maps);
3.2 查詢API
- 更多查詢條件設(shè)置參看 https://mybatis.plus/guide/wrapper.html
4. 字段映射與表名映射
問(wèn)題導(dǎo)入
思考表的字段和實(shí)體類的屬性不對(duì)應(yīng),查詢會(huì)怎么樣?
4.1 問(wèn)題一:表字段與編碼屬性設(shè)計(jì)不同步
- 在模型類屬性上方,使用 @TableField 屬性注解,通過(guò) value 屬性,設(shè)置當(dāng)前屬性對(duì)應(yīng)的數(shù)據(jù)庫(kù)表中的字段關(guān)系。
4.2 問(wèn)題二:編碼中添加了數(shù)據(jù)庫(kù)中未定義的屬性
- 在模型類屬性上方,使用 @TableField 注解,通過(guò) exist 屬性,設(shè)置屬性在數(shù)據(jù)庫(kù)表字段中是否存在,默認(rèn)為true。此屬性無(wú)法與value合并使用。
4.3 問(wèn)題三:采用默認(rèn)查詢開放了更多的字段查看權(quán)限
- 在模型類屬性上方,使用 @TableField 注解,通過(guò) select 屬性:設(shè)置該屬性是否參與查詢。此屬性與select()映射配置不沖突。
4.4 問(wèn)題四:表名與編碼開發(fā)設(shè)計(jì)不同步
- 在模型類上方,使用 @TableName 注解,通過(guò) value 屬性,設(shè)置當(dāng)前類對(duì)應(yīng)的數(shù)據(jù)庫(kù)表名稱。
@Data
@TableName("tbl_user")
public class User {
/*
id為L(zhǎng)ong類型,因?yàn)閿?shù)據(jù)庫(kù)中id為bigint類型,
并且mybatis有自己的一套id生成方案,生成出來(lái)的id必須是Long類型
*/
private Long id;
private String name;
@TableField(value = "pwd",select = false)
private String password;
private Integer age;
private String tel;
@TableField(exist = false) //表示online字段不參與CRUD操作
private Boolean online;
}
四 DML編程控制(增刪改)
1. id生成策略控制(Insert)
問(wèn)題導(dǎo)入
主鍵生成的策略有哪幾種方式?
不同的表應(yīng)用不同的id生成策略
- 日志:自增(1,2,3,4,……)
- 購(gòu)物訂單:特殊規(guī)則(FQ23948AK3843)
- 外賣單:關(guān)聯(lián)地區(qū)日期等信息(10 04 20200314 34 91)
- 關(guān)系表:可省略id
- ……
1.1 id生成策略控制(@TableId注解)
- 名稱:@TableId
- 類型:屬性注解
- 位置:模型類中用于表示主鍵的屬性定義上方
- 作用:設(shè)置當(dāng)前類中主鍵屬性的生成策略
- 相關(guān)屬性
- type:設(shè)置主鍵屬性的生成策略,值參照IdType枚舉值
-
value:設(shè)置數(shù)據(jù)庫(kù)主鍵名稱
1.2 全局策略配置
mybatis-plus:
global-config:
db-config:
id-type: auto
table-prefix: tbl_
id生成策略全局配置
表名前綴全局配置
2. 多記錄操作(批量Delete/Select)
問(wèn)題導(dǎo)入
MyBatisPlus是否支持批量操作?
2.1 按照主鍵刪除多條記錄
//刪除指定多條數(shù)據(jù)
List<Long> list = new ArrayList<>();
list.add(1402551342481838081L);
list.add(1402553134049501186L);
list.add(1402553619611430913L);
userDao.deleteBatchIds(list);
2.2 根據(jù)主鍵查詢多條記錄
//查詢指定多條數(shù)據(jù)
List<Long> list = new ArrayList<>();
list.add(1L);
list.add(3L);
list.add(4L);
userDao.selectBatchIds(list);
3. 邏輯刪除(Delete/Update)
問(wèn)題導(dǎo)入
在實(shí)際環(huán)境中,如果想刪除一條數(shù)據(jù),是否會(huì)真的從數(shù)據(jù)庫(kù)中刪除該條數(shù)據(jù)?
- 刪除操作業(yè)務(wù)問(wèn)題:業(yè)務(wù)數(shù)據(jù)從數(shù)據(jù)庫(kù)中丟棄
- 邏輯刪除:為數(shù)據(jù)設(shè)置是否可用狀態(tài)字段,刪除時(shí)設(shè)置狀態(tài)字段為不可用狀態(tài),數(shù)據(jù)保留在數(shù)據(jù)庫(kù)中
3.1 邏輯刪除案例
①:數(shù)據(jù)庫(kù)表中添加邏輯刪除標(biāo)記字段默認(rèn)值為0
②:實(shí)體類中添加對(duì)應(yīng)字段,并設(shè)定當(dāng)前字段為邏輯刪除標(biāo)記字段
package com.itheima.domain;
import com.baomidou.mybatisplus.annotation.*;
import lombok.Data;
@Data
public class User {
private Long id;
//邏輯刪除字段,標(biāo)記當(dāng)前記錄是否被刪除
@TableLogic(value = "0",delval = "1")
private Integer deleted;
}
③:配置邏輯刪除字面值
mybatis-plus:
global-config:
db-config:
table-prefix: tbl_
# 邏輯刪除字段名
logic-delete-field: deleted
# 邏輯刪除字面值:未刪除為0
logic-not-delete-value: 0
# 邏輯刪除字面值:刪除為1
logic-delete-value: 1
邏輯刪除本質(zhì):邏輯刪除的本質(zhì)其實(shí)是修改操作。如果加了邏輯刪除字段,查詢數(shù)據(jù)時(shí)也會(huì)自動(dòng)帶上邏輯刪除字段。
4. 樂(lè)觀鎖(Update)
問(wèn)題導(dǎo)入
樂(lè)觀鎖主張的思想是什么?
- 業(yè)務(wù)并發(fā)現(xiàn)象帶來(lái)的問(wèn)題:秒殺
4.1 樂(lè)觀鎖案例
①:數(shù)據(jù)庫(kù)表中添加鎖標(biāo)記字段默認(rèn)值為1
②:實(shí)體類中添加對(duì)應(yīng)字段,并設(shè)定當(dāng)前字段為邏輯刪除標(biāo)記字段
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
public class User {
private Long id;
@Version
private Integer version;
}
③:配置樂(lè)觀鎖攔截器實(shí)現(xiàn)鎖機(jī)制對(duì)應(yīng)的動(dòng)態(tài)SQL語(yǔ)句拼裝
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.添加樂(lè)觀鎖攔截器
mpInterceptor.addInnerInterceptor(new OptimisticLockerInnerInterceptor());
return mpInterceptor;
}
}
④:使用樂(lè)觀鎖機(jī)制在修改前必須先獲取到對(duì)應(yīng)數(shù)據(jù)的verion方可正常進(jìn)行
@Test
public void testUpdate() {
/*User user = new User();
user.setId(3L);
user.setName("Jock666");
user.setVersion(1);
userDao.updateById(user);*/
//1.先通過(guò)要修改的數(shù)據(jù)id將當(dāng)前數(shù)據(jù)查詢出來(lái)
//User user = userDao.selectById(3L);
//2.將要修改的屬性逐一設(shè)置進(jìn)去
//user.setName("Jock888");
//userDao.updateById(user);
//1.先通過(guò)要修改的數(shù)據(jù)id將當(dāng)前數(shù)據(jù)查詢出來(lái)
User user = userDao.selectById(3L); //version=3
User user2 = userDao.selectById(3L); //version=3
user2.setName("Jock aaa");
userDao.updateById(user2); //version=>4
user.setName("Jock bbb");
userDao.updateById(user); //verion=3?條件還成立嗎?
}
文章來(lái)源:http://www.zghlxwxcb.cn/news/detail-700773.html
五 快速開發(fā)-代碼生成器
問(wèn)題導(dǎo)入
如果只給一張表的字段信息,能夠推演出Domain、Dao層的代碼?文章來(lái)源地址http://www.zghlxwxcb.cn/news/detail-700773.html
1. MyBatisPlus提供模板
- Mapper接口模板
- 實(shí)體對(duì)象類模板
2. 工程搭建和基本代碼編寫
- 第一步:創(chuàng)建SpringBoot工程,添加代碼生成器相關(guān)依賴
<dependencies>
<!--spring webmvc-->
<dependency>
<groupId>com.baomidou</groupId>
<artifactId>mybatis-plus-boot-starter</artifactId>
<version>3.5.2</version>
</dependency>
<!--druid-->
<dependency>
<groupId>com.alibaba</groupId>
<artifactId>druid</artifactId>
<version>1.2.8</version>
</dependency>
<!--mybatisplus-->
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter</artifactId>
</dependency>
<!--mysql-->
<dependency>
<groupId>mysql</groupId>
<artifactId>mysql-connector-java</artifactId>
<scope>runtime</scope>
</dependency>
<!--test-->
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-test</artifactId>
<scope>test</scope>
</dependency>
<!--lombok-->
<dependency>
<groupId>org.projectlombok</groupId>
<artifactId>lombok</artifactId>
<version>1.18.20</version>
</dependency>
<!--代碼生成器-->
<dependency>
<groupId>com.baomidou</groupId>
<artifactId>mybatis-plus-generator</artifactId>
<version>3.4.1</version>
</dependency>
<!--velocity模板引擎-->
<dependency>
<groupId>org.apache.velocity</groupId>
<artifactId>velocity-engine-core</artifactId>
<version>2.3</version>
</dependency>
</dependencies>
- 第二步:編寫代碼生成器類
package com.itheima;
import com.baomidou.mybatisplus.generator.AutoGenerator;
import com.baomidou.mybatisplus.generator.config.DataSourceConfig;
public class Generator {
public static void main(String[] args) {
//1. 創(chuàng)建代碼生成器對(duì)象,執(zhí)行生成代碼操作
AutoGenerator autoGenerator = new AutoGenerator();
//2. 數(shù)據(jù)源相關(guān)配置:讀取數(shù)據(jù)庫(kù)中的信息,根據(jù)數(shù)據(jù)庫(kù)表結(jié)構(gòu)生成代碼
DataSourceConfig dataSource = new DataSourceConfig();
dataSource.setDriverName("com.mysql.cj.jdbc.Driver");
dataSource.setUrl("jdbc:mysql://localhost:3306/mybatisplus_db?characterEncoding=utf8&useSSL=false&serverTimezone=Asia/Shanghai&rewriteBatchedStatements=true");
dataSource.setUsername("root");
dataSource.setPassword("root");
autoGenerator.setDataSource(dataSource);
//3. 執(zhí)行生成操作
autoGenerator.execute();
}
}
3. 開發(fā)者自定義配置
- 設(shè)置全局配置
//設(shè)置全局配置
GlobalConfig globalConfig = new GlobalConfig();
globalConfig.setOutputDir(System.getProperty("user.dir")+"/mybatisplus_04_generator/src/main/java"); //設(shè)置代碼生成位置
globalConfig.setOpen(false); //設(shè)置生成完畢后是否打開生成代碼所在的目錄
globalConfig.setAuthor("黑馬程序員"); //設(shè)置作者
globalConfig.setFileOverride(true); //設(shè)置是否覆蓋原始生成的文件
globalConfig.setMapperName("%sDao"); //設(shè)置數(shù)據(jù)層接口名,%s為占位符,指代模塊名稱
globalConfig.setIdType(IdType.ASSIGN_ID); //設(shè)置Id生成策略
autoGenerator.setGlobalConfig(globalConfig);
- 設(shè)置包名相關(guān)配置
//設(shè)置包名相關(guān)配置
PackageConfig packageInfo = new PackageConfig();
packageInfo.setParent("com.aaa"); //設(shè)置生成的包名,與代碼所在位置不沖突,二者疊加組成完整路徑
packageInfo.setEntity("domain"); //設(shè)置實(shí)體類包名
packageInfo.setMapper("dao"); //設(shè)置數(shù)據(jù)層包名
autoGenerator.setPackageInfo(packageInfo);
- 策略設(shè)置
//策略設(shè)置
StrategyConfig strategyConfig = new StrategyConfig();
strategyConfig.setInclude("tbl_user"); //設(shè)置當(dāng)前參與生成的表名,參數(shù)為可變參數(shù)
strategyConfig.setTablePrefix("tbl_"); //設(shè)置數(shù)據(jù)庫(kù)表的前綴名稱,模塊名 = 數(shù)據(jù)庫(kù)表名 - 前綴名 例如: User = tbl_user - tbl_
strategyConfig.setRestControllerStyle(true); //設(shè)置是否啟用Rest風(fēng)格
strategyConfig.setVersionFieldName("version"); //設(shè)置樂(lè)觀鎖字段名
strategyConfig.setLogicDeleteFieldName("deleted"); //設(shè)置邏輯刪除字段名
strategyConfig.setEntityLombokModel(true); //設(shè)置是否啟用lombok
autoGenerator.setStrategy(strategyConfig);
- 以后如需使用修改配置即可使用
package com.itheima;
import com.baomidou.mybatisplus.annotation.IdType;
import com.baomidou.mybatisplus.generator.AutoGenerator;
import com.baomidou.mybatisplus.generator.config.DataSourceConfig;
import com.baomidou.mybatisplus.generator.config.GlobalConfig;
import com.baomidou.mybatisplus.generator.config.PackageConfig;
import com.baomidou.mybatisplus.generator.config.StrategyConfig;
public class CodeGenerator {
public static void main(String[] args) {
//1.獲取代碼生成器的對(duì)象
AutoGenerator autoGenerator = new AutoGenerator();
//設(shè)置數(shù)據(jù)庫(kù)相關(guān)配置
DataSourceConfig dataSource = new DataSourceConfig();
dataSource.setDriverName("com.mysql.cj.jdbc.Driver");
dataSource.setUrl("jdbc:mysql://localhost:3306/mybatisplus_db?characterEncoding=utf8&useSSL=false&serverTimezone=Asia/Shanghai&rewriteBatchedStatements=true");
dataSource.setUsername("root");
dataSource.setPassword("root");
autoGenerator.setDataSource(dataSource);
//設(shè)置全局配置
GlobalConfig globalConfig = new GlobalConfig();
globalConfig.setOutputDir(System.getProperty("user.dir")+"/mybatisplus_04_generator/src/main/java"); //設(shè)置代碼生成位置
globalConfig.setOpen(false); //設(shè)置生成完畢后是否打開生成代碼所在的目錄
globalConfig.setAuthor("程序員"); //設(shè)置作者
globalConfig.setFileOverride(true); //設(shè)置是否覆蓋原始生成的文件
globalConfig.setMapperName("%sDao"); //設(shè)置數(shù)據(jù)層接口名,%s為占位符,指代模塊名稱
globalConfig.setIdType(IdType.ASSIGN_ID); //設(shè)置Id生成策略
autoGenerator.setGlobalConfig(globalConfig);
//設(shè)置包名相關(guān)配置
PackageConfig packageInfo = new PackageConfig();
packageInfo.setParent("com.aaa"); //設(shè)置生成的包名,與代碼所在位置不沖突,二者疊加組成完整路徑
packageInfo.setEntity("domain"); //設(shè)置實(shí)體類包名
packageInfo.setMapper("dao"); //設(shè)置數(shù)據(jù)層包名
autoGenerator.setPackageInfo(packageInfo);
//策略設(shè)置
StrategyConfig strategyConfig = new StrategyConfig();
strategyConfig.setInclude("tbl_user"); //設(shè)置當(dāng)前參與生成的表名,參數(shù)為可變參數(shù)
strategyConfig.setTablePrefix("tbl_"); //設(shè)置數(shù)據(jù)庫(kù)表的前綴名稱,模塊名 = 數(shù)據(jù)庫(kù)表名 - 前綴名 例如: User = tbl_user - tbl_
strategyConfig.setRestControllerStyle(true); //設(shè)置是否啟用Rest風(fēng)格
strategyConfig.setVersionFieldName("version"); //設(shè)置樂(lè)觀鎖字段名
strategyConfig.setLogicDeleteFieldName("deleted"); //設(shè)置邏輯刪除字段名
strategyConfig.setEntityLombokModel(true); //設(shè)置是否啟用lombok
autoGenerator.setStrategy(strategyConfig);
//2.執(zhí)行生成操作
autoGenerator.execute();
}
}
到了這里,關(guān)于DAY08_MyBatisPlus——入門案例&標(biāo)準(zhǔn)數(shù)據(jù)層開發(fā)CRUD-Lombok-分頁(yè)功能&DQL編程控制&DML編程控制&樂(lè)觀鎖&快速開發(fā)-代碼生成器的文章就介紹完了。如果您還想了解更多內(nèi)容,請(qǐng)?jiān)谟疑辖撬阉鱐OY模板網(wǎng)以前的文章或繼續(xù)瀏覽下面的相關(guān)文章,希望大家以后多多支持TOY模板網(wǎng)!