likes
comments
collection
share

去掉MyBatis-Plus进行表之间关联查询的SQL,可好❓

作者站长头像
站长
· 阅读数 20

💙 题记

学习使人进步,热爱学习,热爱生活!

💜 起因

最近主要负责一个新项目小程序端的接口开发与调试工作。后台使用的框架核心是 SpringBoot+MyBatis-Plus ,也是当下比较主流的。相比较之前 SSM 框架的话,减少了 spring相关的配置和tomcat的配置,开发起来也是比较方便的,速度也提升了不少。但是相比之前的话,sql写的能少一点,sql主要集中在关联查询,还有一些聚合函数方面的(SUM,COUNT)。

在xml写sql实现多表关联查询应用到多查询条件的时候,还是比较好用的。那有没有一种方式可以不用在xml中写sql的吗?答案是肯定有的。有个叫框架叫 MyBatis-Plus-Join

下面进行相关知识的介绍与运用!

❤️ MyBatis-Plus-Join 介绍

主要是对 MyBatis-Plus 进行了升级,增加了多表链接查询功能,减少了在xml中编写sql的方式。

去掉MyBatis-Plus进行表之间关联查询的SQL,可好❓

有兴趣的可以去官网看看,学习学习。 MyBatis-Plus-Join官网

💚 MyBatis-Plus-Join 运用

🌹 数据准备

DROP TABLE IF EXISTS `order1`;
CREATE TABLE `order1` (
  `id` int NOT NULL AUTO_INCREMENT COMMENT '订单ID',
  `order_number` varchar(64) NOT NULL COMMENT '订单编号',
  `user_id` int NOT NULL COMMENT '用户ID',
  `product_name` varchar(128) NOT NULL COMMENT '商品名称',
  `product_price` decimal(10,2) NOT NULL COMMENT '商品价格',
  `create_time` datetime NOT NULL COMMENT '创建时间',
  PRIMARY KEY (`id`),
  UNIQUE KEY `order_number_UNIQUE` (`order_number`)
) ENGINE=InnoDB AUTO_INCREMENT=21 DEFAULT CHARSET=utf8 COMMENT='订单表';

/*Data for the table `order1` */
insert  into `order1`(`id`,`order_number`,`user_id`,`product_name`,`product_price`,`create_time`) values 
(1,'ORD0000000001',1,'iPhone 13 Pro Max',999.99,'2024-07-25 10:00:00'),
(2,'ORD0000000002',1,'Apple AirPods Pro',249.99,'2024-07-25 10:05:00'),
(3,'ORD0000000003',2,'Samsung Galaxy S23',899.99,'2024-07-25 10:15:00'),
(4,'ORD0000000004',2,'Samsung Galaxy Buds 2 Pro',199.99,'2024-07-25 10:20:00'),
(5,'ORD0000000005',3,'Google Pixel 7 Pro',799.99,'2024-07-25 10:30:00'),
(6,'ORD0000000006',3,'Google Nest Hub',99.99,'2024-07-25 10:35:00'),
(7,'ORD0000000007',4,'Huawei P60 Pro',849.99,'2024-07-25 10:45:00'),
(8,'ORD0000000008',4,'Huawei FreeBuds Pro 2',149.99,'2024-07-25 10:50:00'),
(9,'ORD0000000009',5,'Xiaomi Mi 13 Ultra',749.99,'2024-07-25 11:00:00'),
(10,'ORD0000000010',5,'Xiaomi Smart Band 7 Pro',49.99,'2024-07-25 11:05:00'),
(11,'ORD0000000011',6,'OnePlus 11R',699.99,'2024-07-25 11:15:00'),
(12,'ORD0000000012',6,'OnePlus Bullets Wireless Z',39.99,'2024-07-25 11:20:00'),
(13,'ORD0000000013',7,'Apple Watch Series 8',399.99,'2024-07-25 11:30:00'),
(14,'ORD0000000014',7,'Apple Magic Mouse 2',79.99,'2024-07-25 11:35:00'),
(15,'ORD0000000015',8,'Samsung Galaxy Buds 2 Pro',199.99,'2024-07-25 11:45:00'),
(16,'ORD0000000016',8,'Samsung Tab S8',699.99,'2024-07-25 11:50:00'),
(17,'ORD0000000017',9,'Google Home Mini',49.99,'2024-07-25 12:00:00'),
(18,'ORD0000000018',9,'Google Pixel 6a',449.99,'2024-07-25 12:05:00'),
(19,'ORD0000000019',10,'Amazon Echo Dot (5th Gen)',39.99,'2024-07-25 12:15:00'),
(20,'ORD0000000020',10,'Amazon Kindle Paperwhite',129.99,'2024-07-25 12:20:00');

/*Table structure for table `user1` */
DROP TABLE IF EXISTS `user1`;
CREATE TABLE `user1` (
  `id` int NOT NULL AUTO_INCREMENT COMMENT '用户id',
  `name` varchar(64) DEFAULT NULL COMMENT '用户名称',
  `phone` varchar(64) DEFAULT NULL COMMENT '用户电话',
  `age` int DEFAULT NULL COMMENT '用户年龄',
  `address` varchar(128) DEFAULT NULL COMMENT '用户地址',
  PRIMARY KEY (`id`)
) ENGINE=InnoDB AUTO_INCREMENT=11 DEFAULT CHARSET=utf8 COMMENT='用户表';

/*Data for the table `user1` */
insert  into `user1`(`id`,`name`,`phone`,`age`,`address`) values 
(1,'孙一','13800138002',27,'西安市雁塔区'),
(2,'黄二','13900139002',31,'青岛市市南区'),
(3,'张三','13800138000',30,'北京市海淀区'),
(4,'李四','13900139000',25,'上海市浦东新区'),
(5,'王五','13600136000',35,'广州市天河区'),
(6,'赵六','13700137000',28,'深圳市南山区'),
(7,'陈七','13800138001',22,'杭州市西湖区'),
(8,'周八','13900139001',32,'南京市鼓楼区'),
(9,'吴九','13600136001',40,'成都市武侯区'),
(10,'郑十','13700137001',33,'武汉市江汉区');

注意:数据库建表的时候不能使用数据库一些关键字,比如我最开始建表的时候是 Order ,最后改成 order1 。

🌺 Maven 引入

<!--mybatis-plus-join-boot-starter-->
<dependency>
    <groupId>com.github.yulichang</groupId>
    <artifactId>mybatis-plus-join-boot-starter</artifactId>
    <version>1.4.13</version>
</dependency>

🍁 Mapper中extends

public interface OrderMapper extends MPJBaseMapper<Order> {
}

🍃 代码编写

📄 Service代码

public interface IOrderService extends IService<Order> {
    
    /**
     * 获取所有的用户订单列表
     * @return
     */
    public List<UserOrder> getUserOrderList();

    /**
     * 获取所有的用户订单分页
     * @return
     */
    Page<UserOrder> getUserOrderListPage();
    
    /**
     * 根据userId获取用户订单列表
     * @param userId
     * @return
     */
    List<UserOrder> getOrderOfUserId(Integer userId);
}

📃 ServiceImpl 代码

@Service
public class OrderServiceImpl extends ServiceImpl<OrderMapper, Order> implements IOrderService {
    @Resource
    private OrderMapper orderMapper;

    @Override
    public List<UserOrder> getUserOrderList() {
        //定义查询时主表的MPJLambdaWrapper,以此来调用(可认为调用谁的Mapper,谁就是主表)
        MPJLambdaWrapper<Order> wrapper = JoinWrappers.lambda(Order.class);
        //查询订单表中所有的字段
        wrapper.selectAll(Order.class)
                //查询用户表里面的name和phone
                .select(User::getName,User::getPhone)
                //关联用户表,条件为关键表用户表的id与订单表的userId
                .leftJoin(User.class,User::getId,Order::getUserId);
        //执行查询,并返回自定义的返回实体类型
        List<UserOrder> userOrderList=orderMapper.selectJoinList(UserOrder.class, wrapper);
        return userOrderList;
    }

    @Override
    public Page<UserOrder> getUserOrderListPage() {
        //定义查询时主表的MPJLambdaWrapper,以此来调用(可认为调用谁的Mapper,谁就是主表)
        MPJLambdaWrapper<Order> wrapper = new MPJLambdaWrapper<>();
        //查询订单表中所有的字段
        wrapper.selectAll(Order.class)
                //查询用户表里面的name和phone
                .select(User::getName,User::getPhone)
                //关联用户表,条件为关键表用户表的id与订单表的userId
                .leftJoin(User.class,User::getId,Order::getUserId);
        //执行分页查询,并返回自定义的返回实体类型(这块注意:需要启用 mybatis plus 分页插件)
        Page<UserOrder> listPage=orderMapper.selectJoinPage(new Page<>(1, 10),UserOrder.class, wrapper);
        return listPage;
    }

    @Override
    public List<UserOrder> getOrderOfUserId(Integer userId) {
        //定义查询时主表的MPJLambdaWrapper,以此来调用(可认为调用谁的Mapper,谁就是主表)
        MPJLambdaWrapper<Order> wrapper = new MPJLambdaWrapper<>();
        //查询订单表中所有的字段
        wrapper.selectAll(Order.class)
                //查询用户表里面的name和phone
                .select(User::getName,User::getPhone)
                //关联用户表,条件为关键表用户表的id与订单表的userId
                .leftJoin(User.class,User::getId,Order::getUserId)
                //拼接查询条件userId
                .eq(Order::getUserId,userId);
        //执行查询,并返回自定义的返回实体类型
        List<UserOrder> userOrderList=orderMapper.selectJoinList(UserOrder.class, wrapper);
        return userOrderList;
    }
}

🍄 核心查询方法

/**
 * 连表查询返回一条记录
 *
 * @param wrapper joinWrapper
 * @param clazz   resultType
 */
<DTO> DTO selectJoinOne(@Param(Constant.CLAZZ) Class<DTO> clazz,
                        @Param(Constants.WRAPPER) MPJBaseJoin<T> wrapper);

/**
 * 连表查询返回Map
 *
 * @param wrapper joinWrapper
 */
Map<String, Object> selectJoinMap(@Param(Constants.WRAPPER) MPJBaseJoin<T> wrapper);

/**
 * 连表查询返回记录集合
 *
 * @param wrapper joinWrapper
 * @param clazz   resultType
 */
<DTO> List<DTO> selectJoinList(@Param(Constant.CLAZZ) Class<DTO> clazz,
                               @Param(Constants.WRAPPER) MPJBaseJoin<T> wrapper);

/**
 * 连表查询返回Map集合
 *
 * @param wrapper joinWrapper
 */
List<Map<String, Object>> selectJoinMaps(@Param(Constants.WRAPPER) MPJBaseJoin<T> wrapper);

/**
 * 连表查询返回记录集合并分页
 *
 * @param wrapper joinWrapper
 * @param clazz   resultType
 * @param <DTO>   分页返回对象
 */
<DTO, P extends IPage<DTO>> P selectJoinPage(P page,
                                             @Param(Constant.CLAZZ) Class<DTO> clazz,
                                             @Param(Constants.WRAPPER) MPJBaseJoin<T> wrapper);

/**
 * 连表查询返回Map集合并分页
 *
 * @param wrapper joinWrapper
 */
<P extends IPage<Map<String, Object>>> P selectJoinMapsPage(P page,
                                                            @Param(Constants.WRAPPER) MPJBaseJoin<T> wrapper);

🌵 备注

去掉MyBatis-Plus进行表之间关联查询的SQL,可好❓

可以继承MPJBaseMapper、MPJBaseService、MPJBaseServiceImpl,里面已经继承好了MyBatis-Plus 中的BaseMapper、BaseService、BaseServiceImpl。但是需要用到关联查询的时候需要继承 MPJBaseMapper,其他场景可自行斟酌。

支持原有LambdaWrapper对应的写法,比如:select、eq、like、orderBy等等。

增加了关联查询(leftJoin、join、rightJoin)、可设置字段别名(selectAs)、 查询那个实体类的所有字段(selectAll)等等。

🌴 源码地址

有需要的可以去下载呦!!!

🌲 总结

学习了一次,也写出了简单了实例代码,一切的一切都根据实际项目情况来定。

如果大家使用 MyBatis-Plus 框架的话,在一定程度上给大家提供一个可以不用在xml中编写sql的解决方法。

💖 展望

前路漫漫,还需继续努力!

每一天都是新的开始,做好今天就好!

转载自:https://juejin.cn/post/7395523104742359079
评论
请登录