隨着 Mybatis-plus 的興起,越來越多小伙伴開始接觸和使用這一【偷懶神器】,誰用誰知道,操作單表sql使用條件構造器簡直不要太爽!
但是近期在好幾個 "上班划水群" 看到這樣的提問:"請問有人用mybaits-plus操作過多表查詢嗎?"、"請問mybaits-plus關聯表查詢條件構造器怎么用啊?"、"mybaits-plus 好像不支持多表條件查詢吧?"
針對這一問題,下面做一個簡單的學習記錄與分享,如果你也有這樣的疑問,那么,借我5分鍾的時間,看下去吧。
1、首先我們看mp的條件構造器幫我們做了什么:
舉例一個最簡單的條件查詢:
QueryWrapper<User> queryWrapper = new QueryWrapper<>();
queryWrapper.eq("username", "zyf");
List<User> list = userService.list(queryWrapper);
看控制台執行的sql日志:
可以看到最后執行sql語句就是:
SELECT id,username,password FROM user WHERE username = "zyf";
所以 Wrapper 就是在sql語句后面拼接了詢條件,那么單表設置查詢條件很簡單,QueryWrapper一直點就是了,那么多表呢?
2、看官網:
其實針對這個問題,MP官網就給出了答案,就在條件構造器這一欄的最下面,藏的挺深(doge)
大概的意思就是將條件構造器 Wrapper 作為一個參數 傳入xml 文件。
現在再回到問題的關鍵:【操作多表】,作為一個CRUD工程師,遇到操作多表的需求,第一時間應該想到的就是在xml文件里面寫sql語句將表關聯起來,而mybaits-plus "剛好" 支持將條件構造器作為參數傳入xml。看到這里是不是已經有思路了呢,讓我們來驗證一下吧。
3、准備數據庫結構
表結構:
sql腳本:
/*
Navicat Premium Data Transfer
Source Server Type : MySQL
Source Server Version : 80018
Source Schema : blog_demo
Target Server Type : MySQL
Target Server Version : 80018
File Encoding : 65001
Date: 11/08/2021 23:27:08
*/
SET NAMES utf8mb4;
SET FOREIGN_KEY_CHECKS = 0;
-- ----------------------------
-- Table structure for user
-- ----------------------------
DROP TABLE IF EXISTS `user`;
CREATE TABLE `user` (
`id` bigint(19) NOT NULL AUTO_INCREMENT COMMENT ' ',
`username` varchar(64) CHARACTER SET utf8mb4 COLLATE utf8mb4_0900_ai_ci NULL DEFAULT NULL COMMENT '用戶名',
`password` varchar(64) CHARACTER SET utf8mb4 COLLATE utf8mb4_0900_ai_ci NULL DEFAULT NULL COMMENT '密碼',
PRIMARY KEY (`id`) USING BTREE
) ENGINE = InnoDB CHARACTER SET = utf8mb4 COLLATE = utf8mb4_0900_ai_ci ROW_FORMAT = Dynamic;
-- ----------------------------
-- Records of user
-- ----------------------------
INSERT INTO `user` VALUES (1, 'zyf', '123456');
INSERT INTO `user` VALUES (2, 'admin', 'root');
INSERT INTO `user` VALUES (3, 'test', '123456');
INSERT INTO `user` VALUES (4, 'zhangsan', '123456');
INSERT INTO `user` VALUES (5, 'lisi', '123456');
INSERT INTO `user` VALUES (6, 'wangwu', '123456');
-- ----------------------------
-- Table structure for user_info
-- ----------------------------
DROP TABLE IF EXISTS `user_info`;
CREATE TABLE `user_info` (
`id` bigint(19) NOT NULL AUTO_INCREMENT,
`name` varchar(64) CHARACTER SET utf8mb4 COLLATE utf8mb4_0900_ai_ci NULL DEFAULT NULL COMMENT '姓名',
`gender` int(2) UNSIGNED NULL DEFAULT 0 COMMENT '性別:0-男,1-女',
`age` int(3) NULL DEFAULT 0 COMMENT '年齡',
`user_id` bigint(19) NULL DEFAULT NULL COMMENT 'user表id',
PRIMARY KEY (`id`) USING BTREE
) ENGINE = InnoDB CHARACTER SET = utf8mb4 COLLATE = utf8mb4_0900_ai_ci ROW_FORMAT = Dynamic;
-- ----------------------------
-- Records of user_info
-- ----------------------------
INSERT INTO `user_info` VALUES (1, '奇怪的阿峰', 0, 22, 1);
INSERT INTO `user_info` VALUES (2, '管理員', 0, 40, 2);
INSERT INTO `user_info` VALUES (3, '測試賬號', 0, 21, 3);
INSERT INTO `user_info` VALUES (4, '張三', 1, 22, 4);
INSERT INTO `user_info` VALUES (5, '李四', 1, 28, 5);
INSERT INTO `user_info` VALUES (6, '王五', 0, 19, 6);
SET FOREIGN_KEY_CHECKS = 1;
4、創建一個簡單的SpringBoot
整體結構:
pom文件:
<?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 http://maven.apache.org/xsd/maven-4.0.0.xsd">
<modelVersion>4.0.0</modelVersion>
<groupId>com.zyf</groupId>
<artifactId>blog-demo</artifactId>
<version>1.0-SNAPSHOT</version>
<parent>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-parent</artifactId>
<version>2.2.1.RELEASE</version>
<relativePath/>
</parent>
<dependencies>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-web</artifactId>
</dependency>
<!--mybatisPlus依賴-->
<dependency>
<groupId>com.baomidou</groupId>
<artifactId>mybatis-plus-boot-starter</artifactId>
<version>3.4.1</version>
</dependency>
<dependency>
<groupId>com.baomidou</groupId>
<artifactId>mybatis-plus-generator</artifactId>
<version>3.4.1</version>
</dependency>
<!--mysql-->
<dependency>
<groupId>mysql</groupId>
<artifactId>mysql-connector-java</artifactId>
<version>8.0.15</version>
</dependency>
<!--druid依賴-->
<dependency>
<groupId>com.alibaba</groupId>
<artifactId>druid-spring-boot-starter</artifactId>
<version>1.1.22</version>
</dependency>
<!--lombok用來簡化實體類:需要安裝lombok插件-->
<dependency>
<groupId>org.projectlombok</groupId>
<artifactId>lombok</artifactId>
<scope>provided</scope>
</dependency>
</dependencies>
</project>
yml文件:
server:
port: 8008
spring:
application:
name: @artifactId@
mybatis-plus:
configuration:
log-impl: org.apache.ibatis.logging.stdout.StdOutImpl
mapper-locations: classpath:com/zyf/blog/mapper/xml/*.xml
global-config:
db-config:
logic-delete-value: 1
logic-not-delete-value: 0
datasource:
# type: com.zaxxer.hikari.HikariDataSource
driver-class-name: com.mysql.cj.jdbc.Driver
url: ##這里換成自己的數據庫url
username: #
password: #
hikari:
connection-test-query: SELECT 1
connection-timeout: 600000
idle-timeout: 5000000
max-lifetime: 5400000
maximum-pool-size: 12
minimum-idle: 10
pool-name: GuliHikariPool
#配置mapper xml文件的路徑
mybatis-plus:
configuration:
map-underscore-to-camel-case: true
auto-mapping-behavior: full
log-impl: org.apache.ibatis.logging.stdout.StdOutImpl
mapper-locations: classpath*:mapper/**/*Mapper.xml
MyBatisPlusConfig:
@Configuration
@MapperScan("com.zyf.blog.mapper")
public class MyBatisPlusConfig {
//這個類主要就是用來掃描mapper的,mp提供的插件一般都配置在這里面。
//也可以不寫這個類,直接將@MapperScan("com.zyf.blog.mapper") 注解加到啟動類上
}
controller、entity、service、mapper都是生成器生成的,這里就不貼代碼了,需要完整代碼的小伙伴歡迎訪問鄙人的github,如果對你有幫助的話請順手幫我點個star哦。
5、模擬需求:查詢所有年齡大於20歲的男性用戶
查詢sql:
基於上面的表結構,這里需要連接user表與user_info表
SELECT
u.id AS userId,
u.`password`,
ui.`name`,
ui.gender,
ui.age
FROM
`user` u
LEFT JOIN user_info ui ON u.id = ui.user_id
WHERE
ui.gender = 0
AND ui.age > 20
sql執行結果:
6、代碼實現:
創建UserVO對象
將該對象作為返回給前端的數據模型, 包含user表與user_info表的所有屬性
@Data
public class UserVO {
/** 用戶id */
private Long userId;
/** 用戶名 */
private String username;
/** 密碼 */
private String password;
/** 姓名 */
private String name;
/** 性別:0-男,1-女 */
private Integer gender;
/** 年齡 */
private Integer age;
}
UserController添加一個查詢接口:
/**
* @Author zyf
* @Date 2021/8/11 21:56
* @Version 1.0
*/
@CrossOrigin
@RestController
@RequestMapping("/user")
public class UserController {
@Autowired
private UserService userService;
@GetMapping("/list")
public List<UserVO> list() {
List<UserVO> list = userService.findList();
return list;
}
}
UserService:
/**
* @Author zyf
* @Date 2021/8/11 22:05
* @Version 1.0
*/
public interface UserService extends IService<User> {
List<UserVO> findList();
}
UserServiceImpl:
/**
* @Author zyf
* @Date 2021/8/11 22:06
* @Version 1.0
*/
@Slf4j
@Service
public class UserServiceImpl extends ServiceImpl<UserMapper, User> implements UserService {
@Override
public List<UserVO> findList() {
//注意 這里不能使用LambdaQueryWrapper 為啥?因為LambdaQueryWrapper接收不了 ui.gender 這種參數
QueryWrapper<UserVO> queryWrapper = new QueryWrapper<>();
//沒想到吧!這里可以直接傳 表別名.字段
queryWrapper.eq("ui.gender", 0)
.gt("ui.age", 20);
List<UserVO> list = baseMapper.selectListByQuery(queryWrapper);
return list;
}
}
UserMapper:
/**
* @Author zyf
* @Date 2021/8/11 22:06
* @Version 1.0
*/
public interface UserMapper extends BaseMapper<User> {
//這里注意 @Param(Constants.WRAPPER) 這個參數注解別丟了,否則xml文件里面解析不了會報錯
List<UserVO> selectListByQuery(@Param(Constants.WRAPPER) QueryWrapper<UserVO> queryWrapper);
}
UserMapepr.xml:
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE mapper PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN" "http://mybatis.org/dtd/mybatis-3-mapper.dtd">
<mapper namespace="com.zyf.blog.mapper.UserMapper">
<select id="selectListByQuery" resultType="com.zyf.blog.entity.UserVO">
SELECT
u.id AS userId,
u.`password`,
ui.`name`,
ui.gender,
ui.age
FROM
`user` u
LEFT JOIN user_info ui ON u.id = ui.user_id
<!-- 這就是剛剛注解傳進來的條件構造器 -->
${ew.customSqlSegment}
</select>
</mapper>
7、功能測試
調用接口,查看返回結果:
再看控制台sql日志:
果然,成功將Wrapper設置的查詢條件拼接到sql語句后面了。
大功告成,如果這篇文章對你有幫助的話請順手幫忙點個贊,建議收藏一下,下次要復制粘貼的時候就不會找不到了_。