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日志:

image

可以看到最后執行sql語句就是:
SELECT id,username,password FROM user WHERE username = "zyf";

​ 所以 Wrapper 就是在sql語句后面拼接了詢條件,那么單表設置查詢條件很簡單,QueryWrapper一直點就是了,那么多表呢?

2、看官網:

​ 其實針對這個問題,MP官網就給出了答案,就在條件構造器這一欄的最下面,藏的挺深(doge)

image

​ 大概的意思就是將條件構造器 Wrapper 作為一個參數 傳入xml 文件

​ 現在再回到問題的關鍵:【操作多表】,作為一個CRUD工程師,遇到操作多表的需求,第一時間應該想到的就是在xml文件里面寫sql語句將表關聯起來,而mybaits-plus "剛好" 支持將條件構造器作為參數傳入xml。看到這里是不是已經有思路了呢,讓我們來驗證一下吧。

3、准備數據庫結構

表結構:

image

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

整體結構:

image

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執行結果:

image

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、功能測試

調用接口,查看返回結果:

image

再看控制台sql日志:

​ 果然,成功將Wrapper設置的查詢條件拼接到sql語句后面了。

image

大功告成,如果這篇文章對你有幫助的話請順手幫忙點個贊,建議收藏一下,下次要復制粘貼的時候就不會找不到了_


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM