MybatisPlus多表查询之零sql编写实现

2023-05-16

1.前言

       年初节奏还没有快起来,适合做做技术前瞻,无论是对个人还是团队都是好事。真要说分享,其实感觉也没啥好分享的,就像接手新项目一样,代码都是自己看,别人讲的再多,不看,不用,不踩坑都不会刻骨铭心。
       今天要跟大家分享的mybatisPlus的join查询也是临时起意,早上有同事觉得在mybatisPlus的xml文件里配置子查询不好,嫌弃慢(其实是偷懒了没有正确使用,resultMap没有根据业务自己用自己的,避免多余的子查询),建议在代码层面实现,这里就分享这个join查询如你所愿。

2.分享内容

       MybatisPlus的join查询工具包,这个几乎可以满足零xml的sql编写。实现这一工具包的有2个人,一个是河南的,一个是北京的。个人偏向使用北京小哥实现的,有boot-starter可以支持配置文件,功能更强点。

3.使用方法

3.1北京小哥的join工具包

3.1.1源码与帮助介绍

Git地址:https://github.com/yulichang/mybatis-plus-join.git
使用帮助:https://ylctmh.com/

3.1.2使用集成

1、依赖引入

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

2、配置
       因为提供了boot-starter,所以可以直接使用配置文件,具体可以查看在线使用帮助。我这里是在多数据源场景下使用的,就不用配置文件了。
配置类
A、 MbatisPlus的配置类增加绑定配置

import com.baomidou.mybatisplus.core.config.GlobalConfig;
import com.baomidou.mybatisplus.extension.plugins.MybatisPlusInterceptor;
import com.baomidou.mybatisplus.extension.plugins.inner.PaginationInnerInterceptor;
import com.github.yulichang.injector.MPJSqlInjector;
import lombok.extern.slf4j.Slf4j;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;

import java.util.Collections;


/**
 * 分页插件配置
 *
 * @author zhengwen
 */
@Slf4j
@Configuration
public class MyBatisPlusConfig {

    /**
     * 分页插件 3.5.X
     */
    @Bean
    public PaginationInnerInterceptor paginationInnerInterceptor() {
        log.debug("注册分页插件");
        PaginationInnerInterceptor paginationInnerInterceptor = new PaginationInnerInterceptor();
        /* 只负责注册分页插件,不具体设置DbType、方言等
        // 设置最大单页限制数量,默认 500 条,-1 不受限制
        paginationInnerInterceptor.setMaxLimit(-1L);
        paginationInnerInterceptor.setDbType(DbType.TDENGINE);
        // 开启 count 的 join 优化,只针对部分 left join
        paginationInnerInterceptor.setOptimizeJoin(true);
        */
        return paginationInnerInterceptor;
    }

    @Bean
    public MybatisPlusInterceptor mybatisPlusInterceptor() {
        MybatisPlusInterceptor mybatisPlusInterceptor = new MybatisPlusInterceptor();
        mybatisPlusInterceptor.setInterceptors(Collections.singletonList(paginationInnerInterceptor()));
        return mybatisPlusInterceptor;
    }

    /**
     * GlobalConfig 配置 MPJSqlInjector
     * 绑定MPJSqlInjector到全局配置
     */
    @Bean
    public GlobalConfig globalConfig(MPJSqlInjector mpjSqlInjector) {
        GlobalConfig config = new GlobalConfig();
        //绑定 mpjSqlInjector到全局配置
        config.setSqlInjector(mpjSqlInjector);
        //其他配置 略
        return config;
    }


}

B、 Mysql数据源配置注入全局配置
如果不是多数据源其实可以直接在MybatisPlus里的SqlSessionFactory注入全局配置。我这里是在Mysql数据源配置类注入配置。
MysqlServerConfig配置类的SqlSessionFactory增加配置

import com.baomidou.mybatisplus.annotation.DbType;
import com.baomidou.mybatisplus.core.config.GlobalConfig;
import com.baomidou.mybatisplus.extension.plugins.MybatisPlusInterceptor;
import com.baomidou.mybatisplus.extension.plugins.inner.PaginationInnerInterceptor;
import com.baomidou.mybatisplus.extension.spring.MybatisSqlSessionFactoryBean;
import org.apache.ibatis.session.SqlSessionFactory;
import org.mybatis.spring.SqlSessionTemplate;
import org.mybatis.spring.annotation.MapperScan;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Qualifier;
import org.springframework.boot.context.properties.ConfigurationProperties;
import org.springframework.boot.jdbc.DataSourceBuilder;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.context.annotation.Primary;
import org.springframework.core.io.support.PathMatchingResourcePatternResolver;
import org.springframework.jdbc.datasource.DataSourceTransactionManager;

import javax.sql.DataSource;
import java.util.Collections;


/**
 * mysql配置类
 *
 * @author zhengwen
 */
@Configuration
@MapperScan(basePackages = {"com.xiaotian.datatrans.mapper.mysql"}, sqlSessionTemplateRef = "mysqlSqlSessionTemplate")
public class MysqlServerConfig {

    @Autowired
    private PaginationInnerInterceptor paginationInnerInterceptor;

    private static final String MAPPER_LOCATION = "classpath:mapper/mysql/*.xml";

    @Bean(name = "mysqlDataSource")
    @ConfigurationProperties(prefix = "spring.datasource.mysql-service")
    @Primary
    public DataSource mysqlDataSource() {
        return DataSourceBuilder.create().build();
    }

    @Bean(name = "mysqlSqlSessionFactory")
    @Primary
    public SqlSessionFactory mysqlSqlSessionFactory(@Qualifier("mysqlDataSource") DataSource dataSource, GlobalConfig globalConfig) throws Exception {
        MybatisSqlSessionFactoryBean bean = new MybatisSqlSessionFactoryBean();
        bean.setDataSource(dataSource);
        bean.setMapperLocations(new PathMatchingResourcePatternResolver().getResources(MAPPER_LOCATION));

        //关联SqlSessionFactory与GlobalConfig
        bean.setGlobalConfig(globalConfig);

        //不在这里注入分页插件,会失效,(MyBatisPlusConfig只负责注册分页插件)
        MybatisPlusInterceptor mybatisPlusInterceptor = new MybatisPlusInterceptor();
        paginationInnerInterceptor.setMaxLimit(-1L);
        paginationInnerInterceptor.setDbType(DbType.MYSQL);
        // 开启 count 的 join 优化,只针对部分 left join
        paginationInnerInterceptor.setOptimizeJoin(true);
        mybatisPlusInterceptor.setInterceptors(Collections.singletonList(paginationInnerInterceptor));
        bean.setPlugins(mybatisPlusInterceptor);

        return bean.getObject();
    }

    @Bean(name = "mysqlTransactionManager")
    @Primary
    public DataSourceTransactionManager mysqlTransactionManager(@Qualifier("mysqlDataSource") DataSource dataSource) {
        return new DataSourceTransactionManager(dataSource);
    }

    @Bean(name = "mysqlSqlSessionTemplate")
    @Primary
    public SqlSessionTemplate mysqlSqlSessionTemplate(@Qualifier("mysqlSqlSessionFactory") SqlSessionFactory sqlSessionFactory) throws Exception {
        return new SqlSessionTemplate(sqlSessionFactory);
    }
}

3、Mapper变更
业务mapper原先是继承MybatisPlus的BaseMapper,这里改为继承MPJBaseMapper,点击进去实际上这个接口最终也有继承了BaseMapper的。


/**
 * <p>
 * 设备推送信息表 Mapper 接口
 * </p>
 *
 * @author zhengwen
 * @since 2023-02-03
 */
@DS("mysql-service")
public interface DeviceRecordMapper extends MPJBaseMapper<DeviceRecord> {


    /**
     * 测试
     *
     * @param page
     * @param deviceRecord
     * @return
     */
    IPage<DeviceRecordDto> selectListBy(Page page, @Param("deviceRecord") DeviceRecord deviceRecord);
}

4、service实现使用

/**
 * <p>
 * 设备推送信息表 服务实现类
 * </p>
 *
 * @author zhengwen
 * @since 2023-02-03
 */
@Service
public class DeviceRecordServiceImpl extends ServiceImpl<DeviceRecordMapper, DeviceRecord> implements DeviceRecordService {

    @Autowired
    private DeviceRecordMapper deviceRecordMapper;

    @Override
    public IPage<DeviceRecordDto> selectPage(Page page, DeviceRecord customQueryParams) {
        QueryWrapper<DeviceRecord> qw = new QueryWrapper<>();
        IPage<DeviceRecordDto> records = deviceRecordMapper.selectPage(page, qw);
        //IPage<Student> records = deviceRecordMapper.selectStudentPage(page, customQueryParams);

        return records;

    }

    @Override
    public IPage<DeviceRecordDto> getPageUseJoin(Page page, DeviceRecord customQueryParams) {
        //分页查询
        IPage<DeviceRecordDto> list = deviceRecordMapper.selectJoinPage(page, DeviceRecordDto.class,
                new MPJLambdaWrapper<DeviceRecord>()
                        .selectAll(DeviceRecord.class)
                        //子查询
                        .selectCollection(DeviceRecordInfo.class, DeviceRecordDto::getRecordInfoList)
                        .leftJoin(DeviceRecordInfo.class, DeviceRecordInfo::getRecordId, DeviceRecord::getId));

        return list;
    }
}

3.1.3效果查看

1、2张表的sql
设备推送信息表:device_record
设备上报信息详情:device_record_info

CREATE TABLE `device_record` (
  `id` bigint(20) NOT NULL AUTO_INCREMENT COMMENT '主键',
  `device_no` varchar(100) DEFAULT NULL COMMENT '设备编码',
  `record_time` datetime DEFAULT NULL COMMENT '上报时间',
  `device_type_no` varchar(10) DEFAULT NULL COMMENT '设备类型编码',
  `device_name` varchar(200) DEFAULT NULL COMMENT '设备名称',
  `record_type` varchar(10) DEFAULT NULL COMMENT '上报数据类型',
  `service_id` varchar(20) DEFAULT NULL COMMENT '服务id',
  `record_content` varchar(4000) DEFAULT NULL COMMENT '上报原始内容',
  `create_by` int(11) DEFAULT NULL COMMENT '创建人',
  `create_time` datetime DEFAULT NULL COMMENT '创建时间',
  PRIMARY KEY (`id`)
) ENGINE=InnoDB COMMENT='设备推送信息表';
CREATE TABLE `device_record_info` (
  `id` bigint(20) NOT NULL AUTO_INCREMENT,
  `tag_name` varchar(100) DEFAULT NULL COMMENT '字段名称',
  `tag_key` varchar(50) DEFAULT NULL COMMENT '字段key',
  `tag_val` varchar(50) DEFAULT NULL COMMENT '字段值',
  `record_id` bigint(20) DEFAULT NULL COMMENT '记录id',
  `tag_unit` varchar(30) DEFAULT NULL COMMENT '单位',
  `tag_val_name` varchar(100) DEFAULT NULL COMMENT '字段值释意',
  PRIMARY KEY (`id`)
) ENGINE=InnoDB COMMENT='设备上报信息详情';

2、2张表关系说明
Device_record的主键关联device_record_info的record_id字段:
3、接口请求效果
A、执行的sql
在这里插入图片描述

B、返回的数据
在这里插入图片描述

3.1.4使用总结

1、这里做了个简单示例,它的使用确实应该是可以做到零xml的sql编写的,就看你愿意不。
2、MPJLambdaWrapper增加过滤条件就跟MybatisPlus的QueryWrapper一致。
3、还有很多使用方法,可以自行去在线帮助文档查看,也可以自己在mapper后面“.“的看。
4、个人认为还是挺香的

3.2河南小哥的join工具包

3.2.1源码与帮助介绍

Git地址:https://gitee.com/mhb0409/mybatis-plus-join
使用帮助:就是项目的README.md里介绍

3.2.2使用集成

1、依赖引入

<dependency>
    <groupId>icu.mhb</groupId>
    <artifactId>mybatis-plus-join</artifactId>
    <version>1.3.4</version>
</dependency>

2、配置
A、配置类
MyBatisPlusConfig需要继承JoinDefaultSqlInjector,并且需要重写getMethodList方法

import com.baomidou.mybatisplus.core.injector.AbstractMethod;
import com.baomidou.mybatisplus.core.metadata.TableInfo;
import com.baomidou.mybatisplus.extension.plugins.MybatisPlusInterceptor;
import com.baomidou.mybatisplus.extension.plugins.inner.PaginationInnerInterceptor;
import icu.mhb.mybatisplus.plugln.injector.JoinDefaultSqlInjector;
import lombok.extern.slf4j.Slf4j;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;

import java.util.Collections;
import java.util.List;


/**
 * 分页插件配置
 *
 * @author zhengwen
 */
@Slf4j
@Configuration
public class MyBatisPlusConfig extends JoinDefaultSqlInjector {

    /**
     * 分页插件 3.5.X
     */
    @Bean
    public PaginationInnerInterceptor paginationInnerInterceptor() {
        log.debug("注册分页插件");
        PaginationInnerInterceptor paginationInnerInterceptor = new PaginationInnerInterceptor();
        /* 只负责注册分页插件,不具体设置DbType、方言等
        // 设置最大单页限制数量,默认 500 条,-1 不受限制
        paginationInnerInterceptor.setMaxLimit(-1L);
        paginationInnerInterceptor.setDbType(DbType.TDENGINE);
        // 开启 count 的 join 优化,只针对部分 left join
        paginationInnerInterceptor.setOptimizeJoin(true);
        */
        return paginationInnerInterceptor;
    }

    @Bean
    public MybatisPlusInterceptor mybatisPlusInterceptor() {
        MybatisPlusInterceptor mybatisPlusInterceptor = new MybatisPlusInterceptor();
        mybatisPlusInterceptor.setInterceptors(Collections.singletonList(paginationInnerInterceptor()));
        return mybatisPlusInterceptor;
    }

    
    @Override
    public List<AbstractMethod> getMethodList(Class<?> mapperClass, TableInfo tableInfo) {
        List<AbstractMethod> methodList = super.getMethodList(mapperClass, tableInfo);
        return methodList;
    }
}

B、Mysql数据源配置类
全局配置绑定join的Injector

import com.baomidou.mybatisplus.annotation.DbType;
import com.baomidou.mybatisplus.core.config.GlobalConfig;
import com.baomidou.mybatisplus.extension.plugins.MybatisPlusInterceptor;
import com.baomidou.mybatisplus.extension.plugins.inner.PaginationInnerInterceptor;
import com.baomidou.mybatisplus.extension.spring.MybatisSqlSessionFactoryBean;
import icu.mhb.mybatisplus.plugln.injector.JoinDefaultSqlInjector;
import org.apache.ibatis.session.SqlSessionFactory;
import org.mybatis.spring.SqlSessionTemplate;
import org.mybatis.spring.annotation.MapperScan;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Qualifier;
import org.springframework.boot.context.properties.ConfigurationProperties;
import org.springframework.boot.jdbc.DataSourceBuilder;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.context.annotation.Primary;
import org.springframework.core.io.support.PathMatchingResourcePatternResolver;
import org.springframework.jdbc.datasource.DataSourceTransactionManager;

import javax.sql.DataSource;
import java.util.Collections;


/**
 * mysql配置类
 *
 * @author zhengwen
 */
@Configuration
@MapperScan(basePackages = {"com.xiaotian.datatrans.mapper.mysql"}, sqlSessionTemplateRef = "mysqlSqlSessionTemplate")
public class MysqlServerConfig {

    @Autowired
    private PaginationInnerInterceptor paginationInnerInterceptor;

    private static final String MAPPER_LOCATION = "classpath:mapper/mysql/*.xml";

    @Bean(name = "mysqlDataSource")
    @ConfigurationProperties(prefix = "spring.datasource.mysql-service")
    @Primary
    public DataSource mysqlDataSource() {
        return DataSourceBuilder.create().build();
    }


    @Bean
    public GlobalConfig globalConfig(JoinDefaultSqlInjector joinDefaultSqlInjector) {
        GlobalConfig config = new GlobalConfig();
        //绑定 mpjSqlInjector到全局配置
        config.setSqlInjector(joinDefaultSqlInjector);
        //其他配置 略
        return config;
    }

    @Bean(name = "mysqlSqlSessionFactory")
    @Primary
    public SqlSessionFactory mysqlSqlSessionFactory(@Qualifier("mysqlDataSource") DataSource dataSource, GlobalConfig globalConfig) throws Exception {
        MybatisSqlSessionFactoryBean bean = new MybatisSqlSessionFactoryBean();
        bean.setDataSource(dataSource);
        bean.setMapperLocations(new PathMatchingResourcePatternResolver().getResources(MAPPER_LOCATION));

        //关联SqlSessionFactory与GlobalConfig
        bean.setGlobalConfig(globalConfig);

        //不在这里注入分页插件,会失效,(MyBatisPlusConfig只负责注册分页插件)
        MybatisPlusInterceptor mybatisPlusInterceptor = new MybatisPlusInterceptor();
        paginationInnerInterceptor.setMaxLimit(-1L);
        paginationInnerInterceptor.setDbType(DbType.MYSQL);
        // 开启 count 的 join 优化,只针对部分 left join
        paginationInnerInterceptor.setOptimizeJoin(true);
        mybatisPlusInterceptor.setInterceptors(Collections.singletonList(paginationInnerInterceptor));
        bean.setPlugins(mybatisPlusInterceptor);

        return bean.getObject();
    }

    @Bean(name = "mysqlTransactionManager")
    @Primary
    public DataSourceTransactionManager mysqlTransactionManager(@Qualifier("mysqlDataSource") DataSource dataSource) {
        return new DataSourceTransactionManager(dataSource);
    }

    @Bean(name = "mysqlSqlSessionTemplate")
    @Primary
    public SqlSessionTemplate mysqlSqlSessionTemplate(@Qualifier("mysqlSqlSessionFactory") SqlSessionFactory sqlSessionFactory) throws Exception {
        return new SqlSessionTemplate(sqlSessionFactory);
    }
}

3、springBoot3的启动类还要增加import
否则,查询结果不能成功映射到MybatisPlus的IPage对象的records
启动类上增加注解@Import({JoinInterceptor.class, JoinInterceptorConfig.class})

import icu.mhb.mybatisplus.plugln.interceptor.JoinInterceptor;
import icu.mhb.mybatisplus.plugln.interceptor.JoinInterceptorConfig;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.boot.autoconfigure.domain.EntityScan;
import org.springframework.context.annotation.Import;

/**
 * @author zhengwen
 */

@Import({JoinInterceptor.class, JoinInterceptorConfig.class})
@EntityScan("com.xiaotian")
@SpringBootApplication
public class DataGeniusApplication {

    public static void main(String[] args) {
        SpringApplication.run(DataGeniusApplication.class, args);
        System.out.println("--数据精灵启动成功--");
    }

}

4、Mapper变更
业务mapper原先是继承MybatisPlus的BaseMapper,这里改为继承JoinBaseMapper,点击进去实际上这个接口最终也继承了BaseMapper的。


/**
 * <p>
 * 设备推送信息表 Mapper 接口
 * </p>
 *
 * @author zhengwen
 * @since 2023-02-03
 */
@DS("mysql-service")
public interface DeviceRecordMapper extends JoinBaseMapper<DeviceRecord> {


    /**
     * 测试
     *
     * @param page
     * @param deviceRecord
     * @return
     */
    IPage<DeviceRecordDto> selectListBy(Page page, @Param("deviceRecord") DeviceRecord deviceRecord);
}

5、service实现类使用

/**
 * <p>
 * 设备推送信息表 服务实现类
 * </p>
 *
 * @author zhengwen
 * @since 2023-02-03
 */
@Service
public class DeviceRecordServiceImpl extends ServiceImpl<DeviceRecordMapper, DeviceRecord> implements DeviceRecordService {

    @Autowired
    private DeviceRecordMapper deviceRecordMapper;

    @Override
    public IPage<DeviceRecordDto> selectPage(Page page, DeviceRecord customQueryParams) {
        QueryWrapper<DeviceRecord> qw = new QueryWrapper<>();
        IPage<DeviceRecordDto> records = deviceRecordMapper.selectPage(page, qw);
        //IPage<Student> records = deviceRecordMapper.selectStudentPage(page, customQueryParams);

        return records;

    }

    @Override
    public IPage<DeviceRecordDto> getPageUseJoin(Page page, DeviceRecord customQueryParams) {
         //分页查询
        JoinLambdaWrapper<DeviceRecord> joinLambdaWrapper = new JoinLambdaWrapper<>(DeviceRecord.class);
        joinLambdaWrapper.leftJoin(DeviceRecordInfo.class, DeviceRecordInfo::getRecordId, DeviceRecord::getId)
                .manyToManySelect(DeviceRecordDto::getRecordInfoList,DeviceRecordInfo.class)
                //下面的这个end一定不能少哦,否在sql不会出现 left join xxx
                .end();
        IPage<DeviceRecordDto> list = deviceRecordMapper.joinSelectPage(page, joinLambdaWrapper, DeviceRecordDto.class);

        return list;
    }
}

3.2.3使用效果查看

       效果与3.1.3一致

3.2.4使用总结

1、总体感觉基本与3.1.4一致
2、没有boot-starter感觉没有北京小哥的高大上
3、在线文档没有专门的网址
4、配置略比北京小哥的复杂一丢丢

4.总体感想

  • 首先应该确实可以做到零XML的sql编写了
  • 零sql编写应该是优缺点各一半吧
  • 有没有觉得有了这个,JPA真的是没有必要用了呢?
  • 这2各包在Maven中心库,看到发布第一版时间是同年同月,不过走的方向不一样,一个走插件方式,一个走重写。
  • 2个作者都还在不断更新兼容新版本的MybatisPlus,点赞
  • 2个作者,我也联系到人了,都很友好。就喜欢技术人这种面向问题的交流方式。
           如果有需要,可以去我CSDN的gitCode下载demo,地址:https://gitcode.net/zwrlj527/data-trans.git。这个还是集成上次的多数据源做的集成。更多使用姿势,大家可以自行去他们的帮助文档查看并解锁使用。
           希望可以帮到大家,uping!!!
本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

MybatisPlus多表查询之零sql编写实现 的相关文章

随机推荐

  • js数组对象去重

    removeID span class token operator 61 span span class token punctuation span arr span class token punctuation span span
  • 解决echarts刷新不重绘

    切换筛选条件重新查询时候Echart不重新绘制 需要绘制之前初始化Echart echarts span class token punctuation span span class token function init span sp
  • 判断是否有值,0也是有值的情况

    span class token operator span span class token function isNaN span span class token punctuation span span class token f
  • 基于高德地图SDK进行搜索

    高德地图SDK使用地址http lbs amap com 地图设置 define GDMAPKEY 64 34 key 34 import 34 ViewController h 34 import lt MapKit MapKit h g
  • Microsoft Visual C++ Build Tools.exe安装包损坏

    Python3安装支持库的过程中经常会遇到 Microsoft Visual C 14 0 is required 此时就需要安装Visual C build tools生成工具 在运行build tool安装时 提示安装包损坏 翻墙也无效
  • debian图形界面安装

    安装GNOME中文桌面环境 安装基本的X系统 apt get install x window system core 安装GNOME桌面环境 apt get install gnome 到现在为止 xff0c 我们已成功安装完成gnome
  • Qt 调试时 程序异常结束

    在调试时 xff0c 关闭窗口 xff0c 应用程序输出窗口提示 Qt 调试时 程序异常结束 21 20 48 程序异常结束 21 20 48 The process was ended forcefully 21 20 48 G proj
  • c#webservice的简单示例

    是webservice 就概念上来说 xff0c 可能比较复杂 xff0c 不过我们可以有个宏观的了解 xff1a webservice就是个对外的接口 xff0c 里面有 函数可供外部客户调用 xff08 注意 xff1a 里面同样有客户
  • 实现常规厂家&品牌&型号业务对接物联网平台(snack3加json赋能)

    前言 之前介绍过通过snack3快速对接物模型 xff0c 不知道大家还有没有影响 记得还留了一个作业给大家想想 xff0c 就是这么兼容多型号 多版本 xff0c 这次就来跟大家分享下这么集成多型号 一 物模型文件调整 上次是利用snac
  • 组合OSS服务实现打包业务文件zip下载

    前言 实现文件打包成zip下载 xff0c 支持zip包含目录 文件 废话不多说 xff0c 直接上码 一 设计思路 后端组织文件 xff0c 打包成zip上传到OSS存储返回文件名称给前端前端根据返回的文件名称 xff08 url xff
  • Spring Boot + Disruptor = 王炸!!

    01 背景 工作中遇到项目使用Disruptor做消息队列 对你没看错 不是Kafka 也不是rabbitmq Disruptor有个最大的优点就是快 还有一点它是开源的哦 下面做个简单的记录 02 Disruptor介绍 Disrupto
  • Dbeaver连接ES问题一站解决

    前言 最近几天一直做ES的TPS测试 xff0c 每次看数据ES的数据都在嫌麻烦 xff08 在postman指定索引通过url请求查看数据 xff09 最后决定还是整整Dbeaver连接ES 一 当前境况 1 ES版本比较老 xff0c
  • Dbeaver连接TDengine时序数据库

    前言 还是结合上一阶段的工作 xff0c 为TPS满足合同里的要求 xff0c 预研数据库切换为TDengine 所以查看数据的工具我得能连上去看 xff0c 习惯了Dbeaver xff0c 所以先把Dbeaver整的能连接使用 一 Db
  • idea+ApifoxUploader+Apifox真是内外双修,香

    前言 最近部门为整合后端组 前端组 测试组 需求组 产品组等组之间的工作流程 xff0c 旨在提高协调与高效 xff0c 其中之一就是希望开发组 xff08 后端 前端 xff09 开发的接口能及时更新 xff0c 测试组能做接口测试 xf
  • SpringBoot3+最新MybatisPlus+Mysql与TDengine双数据源

    前言 昨天写的idea 43 Apifox uploader插件 43 apifox新年第一天上班就上榜了 xff0c 真是不错 今天来补一篇 xff0c 本来应该是在前一篇之前发的 实际上就是最新的springBoot集成最新的mybat
  • 业务平台扩展支持TDengine时序数据库方案

    1 场景与架构 1 1业务架构 这里涉及项目隐私 xff0c 架构图不方便公开 大致情况就是 xff1a 应用层的园区畅行 生态宜居 安全守护是我方要交付的系统 平台层的物联网感知中台是我方平台 1 2数据架构 从数据架构看 xff0c 园
  • 物联网平台+业务平台基本架构设计与优化想法

    前言 目前的交付底座有点老 xff0c 而且集成的有点杂 xff0c 计划是要升级下 xff0c 先说想法 xff0c 看领导做不做 1 业务平台定位 我们的愿景 xff1a 通过物联平台赋能 xff0c 让数据产生价值 为客户提供可视化的
  • Qt 正则表达式匹配失败的一个原因

    在Qt中做正则表达式时 xff0c 遇到一个很坑爹的问题 xff0c 还是经验不足导致 在正则表达式中 xff0c 有很多需要元字符 xff0c 是需要使用普通字符加转义符号搭配使用的 比如 w xff0c s 对于这类字符 xff0c 在
  • C++对象模型(整理)

    C 43 43 对象模型 1 何为C 43 43 对象模型 xff1f C 43 43 对象模型可以概括为以下2部分 xff1a 语言中直接支持面向对象程序设计的部分 面向对象程序设计部分 xff1a 如构造函数 析构函数 虚函数 继承 x
  • MybatisPlus多表查询之零sql编写实现

    1 前言 年初节奏还没有快起来 xff0c 适合做做技术前瞻 xff0c 无论是对个人还是团队都是好事 真要说分享 xff0c 其实感觉也没啥好分享的 xff0c 就像接手新项目一样 xff0c 代码都是自己看 xff0c 别人讲的再多 x