赞
踩
以t_order、t_user、t_product三表联合查询为例,其中t_order表为主表。
在springboot项目中,像往常一样正常配置数据源。
首先在项目中引入引入依赖坐标,因为mpj
中依赖较高版本mybatis-plus
中的一些api,所以项目建议直接使用高版本。
- <dependency>
- <groupId>com.github.yulichang</groupId>
- <artifactId>mybatis-plus-join</artifactId>
- <version>1.2.4</version>
- </dependency>
- <dependency>
- <groupId>com.baomidou</groupId>
- <artifactId>mybatis-plus-boot-starter</artifactId>
- <version>3.5.1</version>
- </dependency>
mpj
中也能很好的支持列表查询中的分页功能,首先我们要在项目中加入分页拦截器:
- @Bean
- public MybatisPlusInterceptor mybatisPlusInterceptor(){
- MybatisPlusInterceptor interceptor = new MybatisPlusInterceptor();
- interceptor.addInnerInterceptor(new PaginationInnerInterceptor(DbType.H2));
- return interceptor;
- }
2.
修改Mapper把原Mapper
层接口都是继承的BaseMapper
,改为继承MPJBaseMapper
接口。
- @Mapper
- public interface OrderMapper extends MPJBaseMapper<Order> {
- }
对其余几个参与联表查询的表的Mapper
接口也进行相同的改造。
service
也可以选择继承MPJBaseService
,serviceImpl
选择继承MPJBaseServiceImpl
,这两者为非必须继承。
Mapper
接口改造完成后,我们把它注入到各自Service
中,以t_order
作为主表的话,那么只注入这一个对应的OrderMapper
就可以。
- @Service
- @AllArgsConstructor
- public class OrderServiceImpl implements OrderService {
- private final OrderMapper orderMapper;
- }
- public void page() {
- IPage<OrderDto> orderPage = orderMapper.selectJoinPage(
- new Page<OrderDto>(2,10),
- OrderDto.class,
- new MPJLambdaWrapper<Order>()
- .selectAll(Order.class)
- .select(Product::getUnitPrice)
- .selectAs(User::getName, OrderDto::getUserName)
- .selectAs(Product::getName, OrderDto::getProductName)
- .leftJoin(User.class, User::getId, Order::getUserId)
- .leftJoin(Product.class, Product::getId, Order::getProductId)
- .orderByAsc(Order::getId));
-
- orderPage.getRecords().forEach(System.out::println);
- }
如果不需要分页,则:
- public void getOrder() {
- List<OrderDto> list = orderMapper.selectJoinList(OrderDto.class,
- new MPJLambdaWrapper<Order>()
- .selectAll(Order.class)
- .select(Product::getUnitPrice)
- .selectAs(User::getName,OrderDto::getUserName)
- .selectAs(Product::getName,OrderDto::getProductName)
- .leftJoin(User.class, User::getId, Order::getUserId)
- .leftJoin(Product.class, Product::getId, Order::getProductId)
- .eq(Order::getStatus,3));
-
- list.forEach(System.out::println);
- }
参数OrderDto.class
代表接收返回查询结果的类,作用和我们之前在xml
中写的resultType
类似。
这个类可以直接继承实体,再添加上需要在关联查询中返回的列即可:
- @Data
- @ToString(callSuper = true)
- @EqualsAndHashCode(callSuper = true)
- public class OrderDto extends Order {
- String userName;
- String productName;
- Double unitPrice;
- }
接下来的MPJLambdaWrapper
就是构建查询条件的核心了,看一下我们在上面用到的几个方法:
selectAll()
:查询指定实体类的全部字段select()
:查询指定的字段,支持可变长参数同时查询多个字段,但是在同一个select
中只能查询相同表的字段,所以如果查询多张表的字段需要分开写selectAs()
:字段别名查询,用于数据库字段与接收结果的dto
中属性名称不一致时转换leftJoin()
:左连接,其中第一个参数是参与联表的表对应的实体类,第二个参数是这张表联表的ON
字段,第三个参数是参与联表的ON
的另一个实体类属性除此之外,还可以正常调用mybatis-plus
中的各种原生方法,文档中还提到,默认主表别名是t
,其他的表别名以先后调用的顺序使用t1
、t2
、t3
以此类推。
和mybatis-plus
非常类似,除了MPJLamdaWrapper
外还提供了普通MPJQueryWrapper
,写法上比MPJLambdaWrapper麻烦
。改造上面的代码:
- public void getOrderSimple() {
- List<OrderDto> list = orderMapper.selectJoinList(OrderDto.class,
- new MPJQueryWrapper<Order>()
- .selectAll(Order.class)
- .select("t2.unit_price","t2.name as product_name")
- .select("t1.name as user_name")
- .leftJoin("t_user t1 on t1.id = t.user_id")
- .leftJoin("t_product t2 on t2.id = t.product_id")
- .eq("t.status", "3")
- );
-
- list.forEach(System.out::println);
- }
运行结果与之前完全相同,需要注意的是,这样写时在引用表名时不要使用数据库中的原表名,主表默认使用t
,其他表使用join
语句中我们为它起的别名,如果使用原表名在运行中会出现报错。
并且,在MPJQueryWrapper
中,可以更灵活的支持子查询操作,如果业务比较复杂,那么使用这种方式也是不错的选择。
参考:mybatis-plus的queryWrapper能不能实现表关联? - 知乎
类似的,如果不适用mybatis-plus-join来联合查询,也可以直接使用mybatis-plus的QueryWrapper 来写复杂点的SQL查询,用法如MPJQueryWrapper。
例如:
分页拦截器依然需要:
- @Bean
- public MybatisPlusInterceptor mybatisPlusInterceptor() {
- MybatisPlusInterceptor interceptor = new MybatisPlusInterceptor();
- interceptor.addInnerInterceptor(new PaginationInnerInterceptor(DbType.MYSQL));
- return interceptor;
- }
改造Mapper:
- @Repository
- public interface BlogMapper extends BaseMapper<Blog> {
- /**
- * 静态查询
- */
- @Select("SELECT t_user.user_name " +
- " FROM t_blog, t_user " +
- " WHERE t_blog.id = #{id} " +
- " AND t_blog.user_id = t_user.id")
- String findUserNameByBlogId(@Param("id") Long id);
- * 动态查询
- @Select("SELECT * " +
- " ${ew.customSqlSegment} ")
- IPage<BlogVO> findBlog(IPage<BlogVO> page, @Param("ew") Wrapper wrapper);
- }
改造联合查询:
- public IPage<BlogVO> dynamicQuery(Page<BlogVO> page, String nickName, String title) {
- QueryWrapper<BlogVO> queryWrapper = new QueryWrapper<>();
- queryWrapper.like(StringUtils.hasText(nickName), "t_user.nick_name", nickName);
- queryWrapper.like(StringUtils.hasText(title), "t_blog.title", title);
- queryWrapper.eq("t_blog.deleted_flag", 0);
- queryWrapper.eq("t_user.deleted_flag", 0);
- queryWrapper.apply("t_blog.user_id = t_user.id");
- return blogMapper.findBlog(page, queryWrapper);
- }
查看:MyBatis-Plus怎么实现多表联查 - 开发技术 - 亿速云
不使用Mybatis-plus,和之前一样直接在xml中写SQL。
Copyright © 2003-2013 www.wpsshop.cn 版权所有,并保留所有权利。