当前位置:   article > 正文

Mybatis-plus联表查询 -- mybatis-plus-join_mybatisplus 联表查询

mybatisplus 联表查询

以t_order、t_user、t_product三表联合查询为例,其中t_order表为主表。

0.数据源配置

在springboot项目中,像往常一样正常配置数据源。

1.引入依赖

首先在项目中引入引入依赖坐标,因为mpj中依赖较高版本mybatis-plus中的一些api,所以项目建议直接使用高版本。

  1. <dependency>
  2. <groupId>com.github.yulichang</groupId>
  3. <artifactId>mybatis-plus-join</artifactId>
  4. <version>1.2.4</version>
  5. </dependency>
  6. <dependency>
  7. <groupId>com.baomidou</groupId>
  8. <artifactId>mybatis-plus-boot-starter</artifactId>
  9. <version>3.5.1</version>
  10. </dependency>

2.加入分页拦截器

mpj中也能很好的支持列表查询中的分页功能,首先我们要在项目中加入分页拦截器

  1. @Bean
  2. public MybatisPlusInterceptor mybatisPlusInterceptor(){
  3. MybatisPlusInterceptor interceptor = new MybatisPlusInterceptor();
  4. interceptor.addInnerInterceptor(new PaginationInnerInterceptor(DbType.H2));
  5. return interceptor;
  6. }

2.修改Mapper

把原Mapper层接口都是继承的BaseMapper,改为继承MPJBaseMapper接口。

  1. @Mapper
  2. public interface OrderMapper extends MPJBaseMapper<Order> {
  3. }

 对其余几个参与联表查询的表的Mapper接口也进行相同的改造。

3.修改Service

service也可以选择继承MPJBaseServiceserviceImpl选择继承MPJBaseServiceImpl,这两者为非必须继承。

4.注入Mapper

Mapper接口改造完成后,我们把它注入到各自Service中,以t_order作为主表的话,那么只注入这一个对应的OrderMapper就可以。

  1. @Service
  2. @AllArgsConstructor
  3. public class OrderServiceImpl implements OrderService {
  4. private final OrderMapper orderMapper;
  5. }

5.使用MPJLambdaWrapper联表查询

  1. public void page() {
  2. IPage<OrderDto> orderPage = orderMapper.selectJoinPage(
  3. new Page<OrderDto>(2,10),
  4. OrderDto.class,
  5. new MPJLambdaWrapper<Order>()
  6. .selectAll(Order.class)
  7. .select(Product::getUnitPrice)
  8. .selectAs(User::getName, OrderDto::getUserName)
  9. .selectAs(Product::getName, OrderDto::getProductName)
  10. .leftJoin(User.class, User::getId, Order::getUserId)
  11. .leftJoin(Product.class, Product::getId, Order::getProductId)
  12. .orderByAsc(Order::getId));
  13. orderPage.getRecords().forEach(System.out::println);
  14. }

如果不需要分页,则:

  1. public void getOrder() {
  2. List<OrderDto> list = orderMapper.selectJoinList(OrderDto.class,
  3. new MPJLambdaWrapper<Order>()
  4. .selectAll(Order.class)
  5. .select(Product::getUnitPrice)
  6. .selectAs(User::getName,OrderDto::getUserName)
  7. .selectAs(Product::getName,OrderDto::getProductName)
  8. .leftJoin(User.class, User::getId, Order::getUserId)
  9. .leftJoin(Product.class, Product::getId, Order::getProductId)
  10. .eq(Order::getStatus,3));
  11. list.forEach(System.out::println);
  12. }

参数OrderDto.class代表接收返回查询结果的类,作用和我们之前在xml中写的resultType类似。

这个类可以直接继承实体,再添加上需要在关联查询中返回的列即可:

  1. @Data
  2. @ToString(callSuper = true)
  3. @EqualsAndHashCode(callSuper = true)
  4. public class OrderDto extends Order {
  5. String userName;
  6. String productName;
  7. Double unitPrice;
  8. }

 

接下来的MPJLambdaWrapper就是构建查询条件的核心了,看一下我们在上面用到的几个方法:

  • selectAll():查询指定实体类的全部字段
  • select():查询指定的字段,支持可变长参数同时查询多个字段,但是在同一个select中只能查询相同表的字段,所以如果查询多张表的字段需要分开写
  • selectAs():字段别名查询,用于数据库字段与接收结果的dto中属性名称不一致时转换
  • leftJoin()左连接,其中第一个参数是参与联表的表对应的实体类,第二个参数是这张表联表的ON字段,第三个参数是参与联表的ON的另一个实体类属性

除此之外,还可以正常调用mybatis-plus中的各种原生方法,文档中还提到,默认主表别名是t,其他的表别名以先后调用的顺序使用t1t2t3以此类推。

 

另:也可以使用MPJQueryWrapper

mybatis-plus非常类似,除了MPJLamdaWrapper外还提供了普通MPJQueryWrapper,写法上比MPJLambdaWrapper麻烦。改造上面的代码:

  1. public void getOrderSimple() {
  2. List<OrderDto> list = orderMapper.selectJoinList(OrderDto.class,
  3. new MPJQueryWrapper<Order>()
  4. .selectAll(Order.class)
  5. .select("t2.unit_price","t2.name as product_name")
  6. .select("t1.name as user_name")
  7. .leftJoin("t_user t1 on t1.id = t.user_id")
  8. .leftJoin("t_product t2 on t2.id = t.product_id")
  9. .eq("t.status", "3")
  10. );
  11. list.forEach(System.out::println);
  12. }

运行结果与之前完全相同,需要注意的是,这样写时在引用表名时不要使用数据库中的原表名,主表默认使用t,其他表使用join语句中我们为它起的别名,如果使用原表名在运行中会出现报错。

并且,在MPJQueryWrapper中,可以更灵活的支持子查询操作,如果业务比较复杂,那么使用这种方式也是不错的选择。

参考:mybatis-plus的queryWrapper能不能实现表关联? - 知乎

QueryWrapper

类似的,如果不适用mybatis-plus-join来联合查询,也可以直接使用mybatis-plus的QueryWrapper 来写复杂点的SQL查询,用法如MPJQueryWrapper。

例如:

分页拦截器依然需要:

  1. @Bean
  2. public MybatisPlusInterceptor mybatisPlusInterceptor() {
  3. MybatisPlusInterceptor interceptor = new MybatisPlusInterceptor();
  4. interceptor.addInnerInterceptor(new PaginationInnerInterceptor(DbType.MYSQL));
  5. return interceptor;
  6. }

改造Mapper:

  1. @Repository
  2. public interface BlogMapper extends BaseMapper<Blog> {
  3. /**
  4. * 静态查询
  5. */
  6. @Select("SELECT t_user.user_name " +
  7. " FROM t_blog, t_user " +
  8. " WHERE t_blog.id = #{id} " +
  9. " AND t_blog.user_id = t_user.id")
  10. String findUserNameByBlogId(@Param("id") Long id);
  11. * 动态查询
  12. @Select("SELECT * " +
  13. " ${ew.customSqlSegment} ")
  14. IPage<BlogVO> findBlog(IPage<BlogVO> page, @Param("ew") Wrapper wrapper);
  15. }

 改造联合查询:

  1. public IPage<BlogVO> dynamicQuery(Page<BlogVO> page, String nickName, String title) {
  2. QueryWrapper<BlogVO> queryWrapper = new QueryWrapper<>();
  3. queryWrapper.like(StringUtils.hasText(nickName), "t_user.nick_name", nickName);
  4. queryWrapper.like(StringUtils.hasText(title), "t_blog.title", title);
  5. queryWrapper.eq("t_blog.deleted_flag", 0);
  6. queryWrapper.eq("t_user.deleted_flag", 0);
  7. queryWrapper.apply("t_blog.user_id = t_user.id");
  8. return blogMapper.findBlog(page, queryWrapper);
  9. }

查看:MyBatis-Plus怎么实现多表联查 - 开发技术 - 亿速云 

最后保底的办法

不使用Mybatis-plus,和之前一样直接在xml中写SQL。

声明:本文内容由网友自发贡献,不代表【wpsshop博客】立场,版权归原作者所有,本站不承担相应法律责任。如您发现有侵权的内容,请联系我们。转载请注明出处:https://www.wpsshop.cn/w/我家自动化/article/detail/625024
推荐阅读
相关标签
  

闽ICP备14008679号