MyBatis-Plus多表条件查询
随着 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官网](https://mp.baomidou.com/guide "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](https://github.com/zyf1192306713/mp_multiple_table_joins_query "鄙人的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语句后面了。
大功告成,如果这篇文章对你有帮助的话请顺手帮忙点个赞,建议收藏一下,下次要复制粘贴的时候就不会找不到了^_^。
本文是原创文章,采用 CC BY-NC-ND 4.0 协议,完整转载请注明来自 奇怪的阿峰
评论
匿名评论
隐私政策
你无需删除空行,直接评论以获取最佳展示效果