MyBatis-Plus-Join联表查询


MyBatis-Plus-Join

注意:MyBatis-Plus-Join 需要配合 MyBatis-plus 3.3.0 及以上的版本使用

demo示例:https://gitee.com/best_handsome/mybatis-plus-join-demo

官网:https://mybatisplusjoin.com/pages/quickstart/ksks.html

一、导入依赖

<!-- 添加依赖 引入 Spring Boot Starter 父工程-->
<dependency>
    <groupId>com.github.yulichang</groupId>
    <artifactId>mybatis-plus-join-boot-starter</artifactId>
    <version>1.4.7.2</version>
</dependency>
<dependency>
    <groupId>com.baomidou</groupId>
    <artifactId>mybatis-plus-boot-starter</artifactId>
    <version>最新版本</version>
</dependency>

二、service层(可选)

import com.github.yulichang.base.MPJBaseService;
import com.github.yulichang.join.entity.User;
// service
public interface UserService extends MPJBaseService<User> {
}


// 实现类
@Service
public class UserServiceImpl extends MPJBaseServiceImpl<UserMapper, User> implements UserService {
}

三、Mapper层

import com.github.yulichang.base.MPJBaseMapper;
import com.github.yulichang.join.entity.User;
import org.apache.ibatis.annotations.Mapper;

@Mapper
public interface UserMapper extends MPJBaseMapper<User> {
}

@Mapper
public interface UserAddressMapper extends MPJBaseMapper<Address> {
}

四、Entity实体类

import com.baomidou.mybatisplus.annotation.TableId;
import com.baomidou.mybatisplus.annotation.TableLogic;
import com.baomidou.mybatisplus.annotation.TableName;
import com.github.yulichang.join.enums.Sex;
import lombok.Data;
import lombok.EqualsAndHashCode;
import lombok.ToString;
import lombok.experimental.Accessors;

@Data
@Accessors(chain = true)
@TableName("`user`")
public class User extends BaseEntity {

    @TableId
    private Integer id;

    private String name;

    private Sex sex;

    @TableLogic
    private Boolean del;
}

@Data
@Accessors(chain = true)
@TableName("user_address")
public class Address extends BaseEntity{

    @TableId
    private Integer id;
    
    private String address;

    @TableLogic
    private Boolean del;
}

4.2 基础实体类对象

@Data
public abstract class BaseEntity implements Serializable {

    /**
     * 创建时间
     */
    @TableField(fill = FieldFill.INSERT)
    private Date createTime;
    
    /**
     * 最后更新时间
     */
    @TableField(fill = FieldFill.INSERT_UPDATE)
    private Date updateTime;
    
    /**
     * 创建者,目前使用 SysUser 的 id 编号
     */
    @TableField(fill = FieldFill.INSERT)
    private String creator;
    
    /**
     * 更新者,目前使用 SysUser 的 id 编号
     *
     * 使用 String 类型的原因是,未来可能会存在非数值的情况,留好拓展性。
     */
    @TableField(fill = FieldFill.INSERT_UPDATE)
    private String updater;
    
    /**
     * 是否删除
     */
    @TableLogic
    private Boolean deleted;

}

4.3 自动注入通用属性值:

​ creator \ createTime \ updater \ updateTime

自定义实现MetaObjectHandler元对象字段填充控制器抽象类,实现公共字段自动写入

/**
 * 通用参数填充实现类: 实现MetaObjectHandler接口
 *
 * 如果没有显式的对通用参数进行赋值,这里会对通用参数进行填充、赋值
 *
 */
@Component
public class DefaultDBFieldHandler implements MetaObjectHandler {

    @Override
    public void insertFill(MetaObject metaObject) {
        if (Objects.nonNull(metaObject) && metaObject.getOriginalObject() instanceof BaseDO) {
            BaseDO baseDO = (BaseDO) metaObject.getOriginalObject();

            Date current = new Date();
            // 创建时间为空,则以当前时间为插入时间
            if (Objects.isNull(baseDO.getCreateTime())) {
                baseDO.setCreateTime(current);
            }
            // 更新时间为空,则以当前时间为更新时间
            if (Objects.isNull(baseDO.getUpdateTime())) {
                baseDO.setUpdateTime(current);
            }
            
            String userId = ..... 这里自定义实现逻辑,获取当前登录用户
            
            // 当前登录用户不为空,创建人为空,则当前登录用户为创建人
            if (Objects.nonNull(userId) && Objects.isNull(baseDO.getCreator())) {
                baseDO.setCreator(userId.toString());
            }
            // 当前登录用户不为空,更新人为空,则当前登录用户为更新人
            if (Objects.nonNull(userId) && Objects.isNull(baseDO.getUpdater())) {
                baseDO.setUpdater(userId.toString());
            }
        }
    }

    @Override
    public void updateFill(MetaObject metaObject) {
        // 更新时间为空,则以当前时间为更新时间
        Object modifyTime = getFieldValByName("updateTime", metaObject);
        if (Objects.isNull(modifyTime)) {
            setFieldValByName("updateTime", new Date(), metaObject);
        }

        // 当前登录用户不为空,更新人为空,则当前登录用户为更新人
        Object modifier = getFieldValByName("updater", metaObject);
        
        String userId = ..... 这里自定义实现逻辑,获取当前登录用户
        
        if (Objects.nonNull(userId) && Objects.isNull(modifier)) {
            setFieldValByName("updater", userId.toString(), metaObject);
        }
    }
}

五、cofig配置类

import com.baomidou.mybatisplus.annotation.DbType;
import com.baomidou.mybatisplus.autoconfigure.ConfigurationCustomizer;
import com.baomidou.mybatisplus.extension.plugins.MybatisPlusInterceptor;
import com.baomidou.mybatisplus.extension.plugins.inner.PaginationInnerInterceptor;
import org.mybatis.spring.annotation.MapperScan;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;

/**
 * Mybatis-plus: 分页插件。
 */
@Configuration
@MapperScan(basePackages = {"com.goodwe.kafkaapi.mapper"})  // 这里配置,启动类可不用配置。
public class MybatisPlusConfig {

    /**
     * 新的分页插件,一缓和二缓遵循mybatis的规则,需要设置 MybatisConfiguration#useDeprecatedExecutor = false 避免缓存出现问题(该属性会在旧插件移除后一同移除)
     */
    @Bean
    public MybatisPlusInterceptor mybatisPlusInterceptor() {
        MybatisPlusInterceptor interceptor = new MybatisPlusInterceptor();
        // interceptor.addInnerInterceptor(new PaginationInnerInterceptor(DbType.MYSQL));

        // 添加分页插件
        PaginationInnerInterceptor pageInterceptor = new PaginationInnerInterceptor();
        // 设置请求的页面大于最大页后操作,true调回到首页,false继续请求。默认false
        pageInterceptor.setOverflow(false);
        // 单页分页条数限制,默认无限制
        pageInterceptor.setMaxLimit(500L);
        // 设置数据库类型
        pageInterceptor.setDbType(DbType.SQL_SERVER);

        interceptor.addInnerInterceptor(pageInterceptor);

        return interceptor;
    }

    /**
     * 禁用 MyBatis 使用过时的执行器,以确保项目,使用最新版本执行器。
     */
    @Bean
    public ConfigurationCustomizer configurationCustomizer() {
        return configuration -> configuration.setUseDeprecatedExecutor(false);
    }
}

六、yml配置文件(可不配置)

mybatis-plus:
  configuration:
    log-impl: org.apache.ibatis.logging.stdout.StdOutImpl
    
  # 配置 Mybatis-Plus Join 插件
  join:
    # 是否启用 Join 优化插件
    enabled: true
    # 是否打印 SQL 语句
    show-sql: true
  

SpringBoot主启动类:

​ 添加 @MapperScan 注解,扫描 Mapper 文件夹。

@SpringBootApplication
@MapperScan("com.baomidou.mybatisplus.samples.quickstart.mapper")
public class Application {
    public static void main(String[] args) {
        SpringApplication.run(Application.class, args);
    }
}

测试类

@SpringBootTest
class JoinTest {
    @Autowired
    private UserMapper userMapper;

    /**
     * 一对多
     */
    @Test
    void testJoin() {
        MPJLambdaWrapper<UserDO> wrapper = new MPJLambdaWrapper<UserDO>()
                .selectAll(UserDO.class)
                .selectCollection(AddressDO.class, UserDTO::getAddressList)
                .leftJoin(AddressDO.class, AddressDO::getUserId, UserDO::getId)
                .orderByDesc(UserDO::getId);

        List<UserDTO> list = userMapper.selectJoinList(UserDTO.class, wrapper);
        list.forEach(System.out::println);
    }


    /**
     * 简单的分页关联查询 lambda
     */
    @Test
    void test1() {
        IPage<UserDTO> iPage = userMapper.selectJoinPage(new Page<>(1, 10), UserDTO.class,
                MPJWrappers.<UserDO>lambdaJoin()
                        .selectAll(UserDO.class)
                        .select(AddressDO::getAddress)
                        .select(AreaDO::getProvince)
                        .leftJoin(AddressDO.class, AddressDO::getUserId, UserDO::getId)
                        .leftJoin(AreaDO.class, AreaDO::getId, AddressDO::getAreaId));
        iPage.getRecords().forEach(System.out::println);
    }

    /**
     * 简单的关联查询 String
     */
    @Test
    void test2() {
        MPJQueryWrapper<UserDO> wrapper = MPJWrappers.<UserDO>queryJoin()
                .selectAll(UserDO.class)
                .selectAll(AddressDO.class, "addr")
                .selectAll(AreaDO.class, "a")
                .selectIgnore("addr.id", "a.id", "t.del", "addr.del")
                .leftJoin("user_address addr on t.id = addr.user_id")
                .leftJoin("area a on a.id = addr.area_id")
                .eq("t.id", 1);

        List<UserDO> list = userMapper.selectList(wrapper);
        list.forEach(System.out::println);
    }


    /**
     * 简单的分页关联查询 lambda
     * ON语句多条件
     */
    @Test
    void test3() {
        IPage<UserDTO> page = userMapper.selectJoinPage(new Page<>(1, 10), UserDTO.class,
                MPJWrappers.<UserDO>lambdaJoin()
                        .selectAll(UserDO.class)
                        .select(AddressDO::getAddress)
                        .leftJoin(AddressDO.class, on -> on
                                .eq(UserDO::getId, AddressDO::getUserId)
                                .eq(UserDO::getId, AddressDO::getUserId))
                        .eq(UserDO::getId, 1)
                        .and(i -> i.eq(UserDO::getHeadImg, "er")
                                .or()
                                .eq(AddressDO::getUserId, 1))
                        .eq(UserDO::getId, 1));
        page.getRecords().forEach(System.out::println);
    }

    /**
     * 简单的函数使用
     */
    @Test
    void test4() {
        UserDTO one = userMapper.selectJoinOne(UserDTO.class, MPJWrappers.<UserDO>lambdaJoin()
                .selectSum(UserDO::getId)
                .selectMax(UserDO::getId, UserDTO::getHeadImg)
                .leftJoin(AddressDO.class, AddressDO::getUserId, UserDO::getId)
                .eq(UserDO::getId, 1));
        System.out.println(one);
    }


    /**
     * 忽略个别查询字段
     */
    @Test
    void test6() {
        IPage<UserDTO> page = userMapper.selectJoinPage(new Page<>(1, 10), UserDTO.class,
                MPJWrappers.<UserDO>lambdaJoin()
                        .selectAll(UserDO.class)
                        .selectFilter(AddressDO.class, p -> true)
                        .select(AddressDO::getAddress)
                        .leftJoin(AddressDO.class, AddressDO::getUserId, UserDO::getId)
                        .eq(UserDO::getId, 1));
        page.getRecords().forEach(System.out::println);
    }


    /**
     * 关联查询返回map
     */
    @Test
    void test7() {
        List<Map<String, Object>> list = userMapper.selectJoinMaps(MPJWrappers.<UserDO>lambdaJoin()
                .selectAll(UserDO.class)
                .select(AddressDO::getAddress)
                .leftJoin(AddressDO.class, AddressDO::getUserId, UserDO::getId)
                .eq(UserDO::getId, 1));
        list.forEach(System.out::println);
    }
}
  • 9
    点赞
  • 12
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
MyBatis-Plus是一个基于MyBatis的增强工具,它提供了很多便捷的功能来简化开发。在MyBatis-Plus中,实现连表查询可以通过使用Wrapper(条件构造器)来实现。 下面是使用MyBatis-Plus实现连表查询的步骤: 1. 创建Wrapper对象:使用QueryWrapper或者LambdaQueryWrapper来创建一个Wrapper对象,用于构建查询条件。 2. 设置关联表:通过调用Wrapper对象的join方法,传入关联表的表名和关联条件,来设置关联表。 3. 执行查询:通过调用MyBatis-Plus提供的selectList或者selectPage方法,传入Wrapper对象作为参数,来执行查询操作。 下面是一个示例代码,演示如何使用MyBatis-Plus实现连表查询: ```java // 创建Wrapper对象 QueryWrapper<User> wrapper = new QueryWrapper<>(); // 设置关联表 wrapper.join("user_role", "user_role.user_id = user.id") .join("role", "role.id = user_role.role_id") .select("user.id", "user.name", "role.name as roleName"); // 执行查询 List<Map<String, Object>> userList = userMapper.selectMaps(wrapper); ``` 在上面的示例中,我们创建了一个QueryWrapper对象,并通过join方法设置了两个关联表:user_role和role。然后通过select方法指定了需要查询的字段。最后调用selectMaps方法执行查询,并将结果以List<Map<String, Object>>的形式返回。 注意:这里使用了selectMaps方法来返回结果,可以得到一个包含多个Map对象的List,每个Map对象表示一条查询结果,其中key为字段名,value为字段值。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值