首页 > 其他分享 >MyBatisPlus整合mybatisplus-plus和MyBatis-Plus-Join同时支持默认的方法和多表联查加多主键查询

MyBatisPlus整合mybatisplus-plus和MyBatis-Plus-Join同时支持默认的方法和多表联查加多主键查询

时间:2024-12-05 19:11:38浏览次数:8  
标签:tableInfo Join field add TableId new 多表 主键

前情提要:

在工作上的时候遇到一个情况,一个实体类没有唯一主键而是由两到三个字段组成的复合主键比如:

class User {
  
  private String org;
  
  private String userId;

  private String name;  

}

在需求中这种类的主键就是 org+userId 来组成的联合主键,如果使用mp的话不能使用mp自带的方便快捷的XXXById方法了,

因为XXXById方法需要只有一个主键才能使用,并不支持多个的复合主键,@TableId只允许有一个标注,具体源码在TableInfoHelper这个类里面,

 private static void initTableFields(Configuration configuration, Class<?> clazz, GlobalConfig globalConfig, TableInfo tableInfo, List<String> excludeProperty) {
        AnnotationHandler annotationHandler = globalConfig.getAnnotationHandler();
        PostInitTableInfoHandler postInitTableInfoHandler = globalConfig.getPostInitTableInfoHandler();
        Reflector reflector = tableInfo.getReflector();
        List<Field> list = getAllFields(clazz, annotationHandler);
        // 标记是否读取到主键
        boolean isReadPK = false;
        // 是否存在 @TableId 注解
        boolean existTableId = isExistTableId(list, annotationHandler);
        // 是否存在 @TableLogic 注解
        boolean existTableLogic = isExistTableLogic(list, annotationHandler);

        List<TableFieldInfo> fieldList = new ArrayList<>(list.size());
        for (Field field : list) {
            if (excludeProperty.contains(field.getName())) {
                continue;
            }

            boolean isPK = false;
            OrderBy orderBy = annotationHandler.getAnnotation(field, OrderBy.class);
            boolean isOrderBy = orderBy != null;
            /* 主键ID 初始化 */
            if (existTableId) {
                TableId tableId = annotationHandler.getAnnotation(field, TableId.class);
                if (tableId != null) {
                    if (isReadPK) {
                        throw ExceptionUtils.mpe("@TableId can't more than one in Class: \"%s\".", clazz.getName());
                    }

                    initTableIdWithAnnotation(globalConfig, tableInfo, field, tableId);
                    isPK = isReadPK = true;
                }
            } else if (!isReadPK) {
                isPK = isReadPK = initTableIdWithoutAnnotation(globalConfig, tableInfo, field);
            }

            if (isPK) {
                if (orderBy != null) {
                    tableInfo.getOrderByFields().add(new OrderFieldInfo(tableInfo.getKeyColumn(), orderBy.asc(), orderBy.sort()));
                }
                continue;
            }
            final TableField tableField = annotationHandler.getAnnotation(field, TableField.class);

            /* 有 @TableField 注解的字段初始化 */
            if (tableField != null) {
                TableFieldInfo tableFieldInfo = new TableFieldInfo(globalConfig, tableInfo, field, tableField, reflector, existTableLogic, isOrderBy);
                fieldList.add(tableFieldInfo);
                postInitTableInfoHandler.postFieldInfo(tableFieldInfo, configuration);
                continue;
            }

            /* 无 @TableField  注解的字段初始化 */
            TableFieldInfo tableFieldInfo = new TableFieldInfo(globalConfig, tableInfo, field, reflector, existTableLogic, isOrderBy);
            fieldList.add(tableFieldInfo);
            postInitTableInfoHandler.postFieldInfo(tableFieldInfo, configuration);
        }

        /* 字段列表 */
        tableInfo.setFieldList(fieldList);

        /* 未发现主键注解,提示警告信息 */
        if (!isReadPK) {
            logger.warn(String.format("Can not find table primary key in Class: \"%s\".", clazz.getName()));
        }
    }

如果有多个主键,则会报错,如果依旧想用mp来做这种联合主键的查询,那就不使用@TableId注解,它只会⚠警告

public class DefaultSqlInjector extends AbstractSqlInjector {

    @Override
    public List<AbstractMethod> getMethodList(Configuration configuration, Class<?> mapperClass, TableInfo tableInfo) {
        GlobalConfig.DbConfig dbConfig = GlobalConfigUtils.getDbConfig(configuration);
        Stream.Builder<AbstractMethod> builder = Stream.<AbstractMethod>builder()
            .add(new Insert(dbConfig.isInsertIgnoreAutoIncrementColumn()))
            .add(new Delete())
            .add(new Update())
            .add(new SelectCount())
            .add(new SelectMaps())
            .add(new SelectObjs())
            .add(new SelectList());
        if (tableInfo.havePK()) {
            builder.add(new DeleteById())
                .add(new DeleteByIds())
                .add(new UpdateById())
                .add(new SelectById())
                .add(new SelectBatchByIds());
        } else {
            logger.warn(String.format("%s ,Not found @TableId annotation, Cannot use Mybatis-Plus 'xxById' Method.",
                tableInfo.getEntityType()));
        }
        return builder.build().collect(toList());
    }
}

具体就是这里检测的,如果没有标注@TableId则havePk返回的false

然后在查询的时候构建条件

 Wrappers.lambdaQuery().eq(User::getOrg, "org").eq(User::getUserId,"1");

然后执行,就能有联合主键的效果,但是这样每次都要构建条件select,update,都要,个人感觉很不方便,如果一个类还好,当实体类变多了之后这样子就会很麻烦,

这里就要引入今天的主角之一了mybatisplus-plus

<dependency>
        <groupId>com.github.jeffreyning</groupId>
        <artifactId>mybatisplus-plus</artifactId>
        <version>1.7.5-RELEASE</version>
</dependency>

他兼容mp,使用的时候只需要给复合主键标记上他的注解@MppMultiId,表名使用联合主键,即可,这个是兼容@TableId的,可以两个注解同时标注在一个字段上面

class User {

  @MppMultiId
  private String org;
  
  @MppMultiId
  private String userId;

  private String name;  

}

标注完之后,在mapper层继承MppBaseMapper

interface UserMapper extends MppBaseMapper<User>{

}

然后UserMapper就会多以下的方法deleteByMultiId,selectByMultiId,updateByMultiId,方法调用只需要传入对应的实体类,给联合主键赋值就可以了,关于Service层的操作可以查看官方文档 文档

标签:tableInfo,Join,field,add,TableId,new,多表,主键
From: https://www.cnblogs.com/pf666nb/p/18589225

相关文章

  • mysql left join on条件与where条件 统计报表查询方法
    mysqlleftjoinon条件与where条件统计报表查询方法1.确定数据数量,通过简化的sql查找符合条件的订单号列表2.然后根据需求,添加单个的字段,在这个过程中会添加leftjoin左关联表查询需要区分两种情况2.1.可以唯一确定记录的,(SELECTt3.get_car_addrFROM`delivery_addr`t3W......
  • flink学习(13)—— 重试机制和维表join
    重试机制当任务出现异常的时候,会直接停止任务——解决方式,重试机制1、设置checkpoint后,会给任务一个重启策略——无限重启2、可以手动设置任务的重启策略代码设置//开启checkpoint后,默认是无限重启,可以设置该值表示不重启env.setRestartStrategy(RestartStrategies.noRe......
  • 多表设计
    一对多:在数据库中多的一方添加外键来关联另一个表的主键。外键约束语法:1、创建时指定:creattable表名(字段名数据类型...[constrain][外键名称]foreignkey(外键字段名)references主表(主表列名)......
  • MySQL底层概述—8.JOIN排序索引优化
    大纲1.Join算法原理2.IN和EXISTS函数3.MySQL排序之索引排序(Usingindex)4.MySQL排序之额外排序(Usingfilesort)5.排序优化之尽量使用索引排序6.索引单表优化7.索引多表优化 1.Join算法原理(1)Join简介(2)驱动表的定义(3)三种Join算法(4)总结 (1)Join简介Join......
  • 第三十八讲:自增主键为什么不是连续的
    第三十八讲:自增主键为什么不是连续的简概引言​ 在第4篇文章中,我们提到过自增主键,由于自增主键可以让主键索引尽量地保持递增顺序插入,避免了页分裂,因此索引更紧凑。​ 之前我见过有的业务设计依赖于自增主键的连续性,也就是说,这个设计假设自增主键是连续的。​ 但实际上,这......
  • 某j多租户主,多表关联查询 ,主表不追加租户条bug解决
    1.原因经过半天一点点的手撕源码自己重写了TenantLineHandler,但是又重复加了,到这时才意识某j已经重了TenantLineHandler再排查发下他重写的 ignoreTable(StringtableName)中传过来的tableName多加了反引号`,在比较前去掉就好了2.多租户配置类代码<dependency>......
  • GaussDB数据库SQL系列-表连接(JOIN)
    一、前言SQL是用于数据分析和数据处理的最重要的编程语言之一,表连接(JOIN)是数据库中SQL的一种常见操作,在实际应用中,我们需要根据业务需求从两个或多个相关的表中获取信息。二、GaussDBJOINGaussDB是华为推出的企业级分布式关系型数据库。GaussDBJOIN子句是基于两个或者多个表......
  • mysql删除主键和删除索引(含删除unique索引)
    mysql删除主键和删除索引(含删除unique索引)##删除表DROPTABLEconfig_back;##删除主键ALTERTABLEconfig_backDROPPRIMARYKEY;错误代码:1075Incorrecttabledefinition;therecanbeonlyoneautocolumnanditmustbedefinedasakey##测试表CREATETABL......
  • 深入理解 SQL 中的多表查询——以员工信息查询为例
    深入理解SQL中的多表查询——以员工信息查询为例引言在数据库查询中,多表查询是常见的需求。通过多表查询,我们可以从多个表中获取相关联的数据,从而实现更复杂的数据分析和报表生成。本文将通过一个具体的案例,详细解释如何进行多表查询,并揭示一些常见的误区。数据库设计首先,我......
  • GaussDB数据库SQL系列-表连接(JOIN)
    一、前言SQL是用于数据分析和数据处理的最重要的编程语言之一,表连接(JOIN)是数据库中SQL的一种常见操作,在实际应用中,我们需要根据业务需求从两个或多个相关的表中获取信息。二、GaussDBJOINGaussDB是华为推出的企业级分布式关系型数据库。GaussDBJOIN子句是基于两个或者多个表......