這個我們在前面都有見過,比如查詢所有和分頁查詢的時候,都有看到過一個Wrapper
類,這個類就是用來構建查詢條件的,如下圖所示:
那麼條件查詢如何使用Wrapper來構建呢?
在構建條件查詢之前,我們先來準備下環境
建立一個SpringBoot專案
參考Java開發學習(三十五)----SpringBoot快速入門及起步依賴解析
pom.xml中新增對應的依賴
<?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>
</parent>
<groupId>com.itheima</groupId>
<artifactId>mybatisplus_02_dql</artifactId>
<version>0.0.1-SNAPSHOT</version>
<properties>
<java.version>1.8</java.version>
</properties>
<dependencies>
<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>
<dependency>
<groupId>org.projectlombok</groupId>
<artifactId>lombok</artifactId>
</dependency>
</dependencies>
<build>
<plugins>
<plugin>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-maven-plugin</artifactId>
</plugin>
</plugins>
</build>
</project>
編寫UserDao介面
@Mapper
public interface UserDao extends BaseMapper<User> {
}
編寫模型類
@Data
public class User {
private Long id;
private String name;
private String password;
private Integer age;
private String tel;
}
編寫引導類
@SpringBootApplication
public class Mybatisplus02DqlApplication {
public static void main(String[] args) {
SpringApplication.run(Mybatisplus02DqlApplication.class, args);
}
}
編寫組態檔
# 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
# MybatisPlus紀錄檔
mybatis-plus:
configuration:
log-impl: org.apache.ibatis.logging.stdout.StdOutImpl
編寫測試類
@SpringBootTest
class Mybatisplus02DqlApplicationTests {
@Autowired
private UserDao userDao;
@Test
void testGetAll(){
List<User> userList = userDao.selectList(null);
System.out.println(userList);
}
}
最終建立的專案結構為:
測試的時候,控制檯列印的紀錄檔比較多,速度有點慢而且不利於檢視執行結果,所以接下來我們把這個紀錄檔處理下:
取消初始化spring紀錄檔列印,resources目錄下新增logback.xml,名稱固定,內容如下:
<?xml version="1.0" encoding="UTF-8"?>
<configuration>
</configuration>
取消MybatisPlus啟動banner圖示
application.yml新增如下內容:
# mybatis-plus紀錄檔控制檯輸出
mybatis-plus:
configuration:
log-impl: org.apache.ibatis.logging.stdout.StdOutImpl
global-config:
banner: off # 關閉mybatisplus啟動圖示
取消SpringBoot的log列印
application.yml新增如下內容:
spring:
main:
banner-mode: off # 關閉SpringBoot啟動圖示(banner)
解決控制檯列印紀錄檔過多的相關操作可以不用去做,一般會被用來方便我們檢視程式執行的結果。
在進行查詢的時候,我們的入口是在Wrapper這個類上,因為它是一個介面,所以我們需要去找它對應的實現類,關於實現類也有很多,說明我們有多種構建查詢條件物件的方式,
先來看第一種:QueryWrapper
@SpringBootTest
class Mybatisplus02DqlApplicationTests {
@Autowired
private UserDao userDao;
@Test
void testGetAll(){
QueryWrapper qw = new QueryWrapper();
qw.lt("age",18);
List<User> userList = userDao.selectList(qw);
System.out.println(userList);
}
}
lt: 小於(<) ,最終的sql語句為
SELECT id,name,password,age,tel FROM user WHERE (age < ?)
第一種方式介紹完後,有個小問題就是在寫條件的時候,容易出錯,比如age寫錯,就會導致查詢不成功
接著來看第二種:QueryWrapper的基礎上使用lambda
@SpringBootTest
class Mybatisplus02DqlApplicationTests {
@Autowired
private UserDao userDao;
@Test
void testGetAll(){
QueryWrapper<User> qw = new QueryWrapper<User>();
qw.lambda().lt(User::getAge, 10);//新增條件
List<User> userList = userDao.selectList(qw);
System.out.println(userList);
}
}
User::getAge,為lambda表示式中的,類名::方法名,最終的sql語句為:
SELECT id,name,password,age,tel FROM user WHERE (age < ?)
注意:構建LambdaQueryWrapper的時候泛型不能省。
此時我們再次編寫條件的時候,就不會存在寫錯名稱的情況,但是qw後面多了一層lambda()呼叫
接著來看第三種:LambdaQueryWrapper
@SpringBootTest
class Mybatisplus02DqlApplicationTests {
@Autowired
private UserDao userDao;
@Test
void testGetAll(){
LambdaQueryWrapper<User> lqw = new LambdaQueryWrapper<User>();
lqw.lt(User::getAge, 10);
List<User> userList = userDao.selectList(lqw);
System.out.println(userList);
}
}
這種方式就解決了上一種方式所存在的問題。
三種構建查詢物件的方式,每一種都有自己的特點,所以用哪一種都行,剛才都是一個條件,那如果有多個條件該如何構建呢?
需求:查詢資料庫表中,年齡在10歲到30歲之間的使用者資訊
@SpringBootTest
class Mybatisplus02DqlApplicationTests {
@Autowired
private UserDao userDao;
@Test
void testGetAll(){
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);
}
}
gt:大於(>),最終的SQL語句為
SELECT id,name,password,age,tel FROM user WHERE (age < ? AND age > ?)
構建多條件的時候,可以支援鏈式程式設計
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);
需求:查詢資料庫表中,年齡小於10或年齡大於30的資料
@SpringBootTest
class Mybatisplus02DqlApplicationTests {
@Autowired
private UserDao userDao;
@Test
void testGetAll(){
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);
}
}
or()就相當於我們sql語句中的or
關鍵字,不加預設是and
,最終的sql語句為:
SELECT id,name,password,age,tel FROM user WHERE (age < ? OR age > ?)
先來看一張圖,
我們在做條件查詢的時候,一般會有很多條件可以供使用者進行選擇查詢。
這些條件使用者可以選擇使用也可以選擇不使用,比如我要查詢價格在8000以上的手機
在輸入條件的時候,價格有一個區間範圍,按照需求只需要在第一個價格輸入框中輸入8000
後臺在做價格查詢的時候,一般會讓 price>值1 and price <值2
因為前端沒有輸入值2,所以如果不處理的話,就會出現 price>8000 and price < null問題
這個時候查詢的結果就會出問題,具體該如何解決?
需求:查詢資料庫表中,根據輸入年齡範圍來查詢符合條件的記錄
使用者在輸入值的時候,
如果只輸入第一個框,說明要查詢大於該年齡的使用者
如果只輸入第二個框,說明要查詢小於該年齡的使用者
如果兩個框都輸入了,說明要查詢年齡在兩個範圍之間的使用者
思考第一個問題:後臺如果想接收前端的兩個資料,該如何接收?
我們可以使用兩個簡單資料型別,也可以使用一個模型類,但是User類中目前只有一個age屬性,如:
@Data
public class User {
private Long id;
private String name;
private String password;
private Integer age;
private String tel;
}
使用一個age屬性,如何去接收頁面上的兩個值呢?這個時候我們有兩個解決方案
方案一:新增屬性age2,這種做法可以但是會影響到原模型類的屬性內容
@Data
public class User {
private Long id;
private String name;
private String password;
private Integer age;
private String tel;
private Integer age2;
}
方案二:新建一個模型類,讓其繼承User類,並在其中新增age2屬性,UserQuery在擁有User屬性後同時新增了age2屬性。
@Data
public class User {
private Long id;
private String name;
private String password;
private Integer age;
private String tel;
}
@Data
public class UserQuery extends User {
private Integer age2;
}
環境準備好後,我們來實現下剛才的需求:
@SpringBootTest
class Mybatisplus02DqlApplicationTests {
@Autowired
private UserDao userDao;
@Test
void testGetAll(){
//模擬頁面傳遞過來的查詢資料
UserQuery uq = new UserQuery();
uq.setAge(10);
uq.setAge2(30);
LambdaQueryWrapper<User> lqw = new LambdaQueryWrapper<User>();
if(null != uq.getAge2()){
lqw.lt(User::getAge, uq.getAge2());
}
if( null != uq.getAge()) {
lqw.gt(User::getAge, uq.getAge());
}
List<User> userList = userDao.selectList(lqw);
System.out.println(userList);
}
}
上面的寫法可以完成條件為非空的判斷,但是問題很明顯,如果條件多的話,每個條件都需要判斷,程式碼量就比較大,來看MybatisPlus給我們提供的簡化方式:
@SpringBootTest
class Mybatisplus02DqlApplicationTests {
@Autowired
private UserDao userDao;
@Test
void testGetAll(){
//模擬頁面傳遞過來的查詢資料
UserQuery uq = new UserQuery();
uq.setAge(10);
uq.setAge2(30);
LambdaQueryWrapper<User> lqw = new LambdaQueryWrapper<User>();
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);
}
}
lt()方法
condition為boolean型別,返回true,則新增條件,返回false則不新增條件
本文來自部落格園,作者:|舊市拾荒|,轉載請註明原文連結:https://www.cnblogs.com/xiaoyh/p/16468183.html