SpringBoot 整合 clickhouse和mysql 手把手教程全网最详细

news2024/11/17 21:28:17

最近做一个项目 需要 整合mysql clickhouse 多数据源

后台用的是ruoyi框架

1. 首先pom引入相关依赖

  <!--JDBC-clickhouse数据库-->
    <dependency>
        <groupId>com.clickhouse</groupId>
        <artifactId>clickhouse-jdbc</artifactId>
        <version>0.3.2</version>	<!-- 0.2.4/0.2.5/0.2.6/0.3.0/0.3.2 -->
    </dependency>

在这里插入图片描述

2. 编写配置文件 application.yml(properties同理)

需要注意的是官网不建议使用ru.yandex.clickhouse驱动,应该改成com.clickhouse驱动,并且推荐使用0.3.2以上的版本

数据源配置

spring:
  datasource:
    type: com.alibaba.druid.pool.DruidDataSource
    druid:
      # 主库数据源  mysql
      master:
        driverClassName: com.mysql.cj.jdbc.Driver
        url: jdbc:mysql://localhost:3306/test?useUnicode=true&characterEncoding=utf8&zeroDateTimeBehavior=convertToNull&useSSL=false&serverTimezone=GMT%2B8
        username: root
        password: 123456
      # 从库数据源   clickhouse
      slave:
        # 从数据源开关/默认关闭
        driverClassName: com.clickhouse.jdbc.ClickHouseDriver
        enabled: true
        url: jdbc:clickhouse://localhost:8123/test
        username: admin
        password: 123456
      # 初始连接数
      initialSize: 10
      # 最小连接池数量
      minIdle: 15
      # 最大连接池数量
      maxActive: 50
      # 配置获取连接等待超时的时间
      maxWait: 60000
      # 配置间隔多久才进行一次检测,检测需要关闭的空闲连接,单位是毫秒
      timeBetweenEvictionRunsMillis: 60000
      # 配置一个连接在池中最小生存的时间,单位是毫秒
      minEvictableIdleTimeMillis: 300000
      # 配置一个连接在池中最大生存的时间,单位是毫秒
      maxEvictableIdleTimeMillis: 900000
      # 配置检测连接是否有效
      validationQuery: SELECT 1
      testWhileIdle: true
      testOnBorrow: false
      testOnReturn: false

3. 实体类

/**
 1. @author WXY
 2. @date 2023/2/24 14:46
 */
public class Curve {
    /** 设备sn */
    private  String sn;
    /** 属性sn */
    private  String psn;
    /** 属性id */
    private  Integer pid;
    /** 值 */
    private Float val;
    /** 时间 */
    @JsonFormat(pattern = "yyyy-MM-dd HH:mm:ss")
    private Date time;

    /** 开始时间 */
    private String startDateTime;
    /** 结束时间 */
    private String  endDateTime;

    /** 设备名称 */
    private String  name;

    /**
     * 表时间
     */
    private String outsideTime;


    public String getOutsideTime() {
        return outsideTime;
    }

    public void setOutsideTime(String outsideTime) {
        this.outsideTime = outsideTime;
    }

    public String getName() {
        return name;
    }

    public void setName(String name) {
        this.name = name;
    }

    public String getSn() {
        return sn;
    }

    public void setSn(String sn) {
        this.sn = sn;
    }

    public String getPsn() {
        return psn;
    }

    public void setPsn(String psn) {
        this.psn = psn;
    }

    public Integer getPid() {
        return pid;
    }

    public void setPid(Integer pid) {
        this.pid = pid;
    }

    public Float getVal() {
        return val;
    }

    public void setVal(Float val) {
        this.val = val;
    }

    public Date getTime() {
        return time;
    }

    public void setTime(Date time) {
        this.time = time;
    }

    public String getStartDateTime() {
        return startDateTime;
    }

    public void setStartDateTime(String startDateTime) {
        this.startDateTime = startDateTime;
    }

    public String getEndDateTime() {
        return endDateTime;
    }

    public void setEndDateTime(String endDateTime) {
        this.endDateTime = endDateTime;
    }
}

4. mapper接口

/**
 1. 【查询clickhouse】Mapper接口
 2. 
 3. @author gjwl
 4. @date 2023-02-24
 */
public interface CurveMapper {
    

    /**
     * 查询【单个曲线】列表
     *
     * @param curve 【曲线】  秒级数据
     * @return 【请填写功能名称】集合
     */
    public List<CurveVo> selectCurveVoList(Curve curve);


    /**
     * 查询单个集合里面最大最小平均值
     *
     * @param curve 【曲线】
     * @return 【查询单个集合里面最大最小平均值】集合
     */
    public Map selectMinAdnMax(Curve curve);
}

5. mapper.xml文件

<?xml version="1.0" encoding="UTF-8" ?>
<!DOCTYPE mapper
PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN"
"http://mybatis.org/dtd/mybatis-3-mapper.dtd">
<mapper namespace="com.xx.xx.mapper.CurveMapper">

    <!--正常实体-->
    <resultMap type="Curve" id="CurveResult">
        <result property="sn"    column="sn"    />
        <result property="psn"    column="psn"    />
        <result property="pid"    column="pid"    />
        <result property="val"    column="val"    />
        <result property="time"    column="time"    />
    </resultMap>

    <sql id="selectCurveVo">
        select val,time from curve
    </sql>


    <!--用于单条曲线-->
    <select id="selectCurveVoList" parameterType="Curve" resultMap="CurveVoResult">
        <include refid="selectCurveVo"/>
        <where>
            <if test="psn != null  and psn != ''"> and psn = #{psn}</if>
            <if test="startDateTime != null "> and time &gt;= #{startDateTime}</if>
            <if test="endDateTime != null "> and time &lt;=  #{endDateTime}</if>
        </where>
        order by time asc
    </select>

    <!--拿最大最小平均值-->
    <select id="selectMinAdnMax" parameterType="Curve" resultType="Map">
        select max(val) as big, min(val) as small, round(avg(val),1) as ag
        from curve
        <where>
            <if test="psn != null  and psn != ''"> and psn = #{psn}</if>
            <if test="startDateTime != null "> and time &gt;= #{startDateTime}</if>
            <if test="endDateTime != null "> and time &lt;=  #{endDateTime}</if>
        </where>
    </select>


</mapper>

6. service类

/**
 * 【查询曲线】Service接口
 * 
 * @author gjwl
 * @date 2022-07-01
 */
public interface ICurveService {


    /**
     * 查询【查询曲线】列表  单条返回
     *
     * @param curve 【查询曲线】
     * @return 【查询曲线】集合
     */
    public List<CurveVo> selectCurveVoList(Curve curve);

    /**
     * 查询【查询曲线】列表  多条返回
     * 分钟级别
     *
     * @param curve 【查询曲线】
     * @return 【查询曲线】集合
     */
    public List<CurveManyVo> selectCurveManyVoList(Curve curve);


    /**
     * 查询【查询曲线】列表  单条返回
     * 带最大最小值
     *
     * @param curve 【查询曲线】
     * @return 【查询曲线】集合
     */
    public Map selectMinAdnMax(Curve curve);

}

7. ServiceImpl类

重点在@DataSource(value = DataSourceType.SLAVE) 注解上 在这里切换从库代表这个类里面的方法都切换成从库的数据库

/**
 * 【查询曲线】Service业务层处理
 *  
 * @author gjwl
 * @date 2022-07-01
 */
@Service
@DataSource(value = DataSourceType.SLAVE)
public class CurveServiceImpl implements ICurveService {

    private static final Logger log = LoggerFactory.getLogger(CurveServiceImpl.class);

    @Autowired
    private RedisCache redisCache;

    @Autowired
    private CurveMapper curveMapper;


    /**
     * 单条曲线使用
     * @param curve 【查询曲线】
     * @return
     */
    @Override
    public List<CurveVo> selectCurveVoList(Curve curve) {
        String key = getCacheDsnKey(Constants.curve, curve.getPsn(), curve.getStartDateTime(), curve.getEndDateTime());
        List<CurveVo> list = curveMapper.selectCurveVoList(curve);
        if (list.size() > 0) {
            redisCache.setCacheList(key, list);
            //使用 删除缓存
            redisCache.expire(key, 2, TimeUnit.MINUTES);
        }
        return list;
    }

	/**
     * 单条曲线使用
     * @param curve 【查询曲线】
     *  最大值最小值平均值
     * @return
     */
    @Override
    public Map selectMinAdnMax(Curve curve) {
        String key = getCacheDsnKey(Constants.curve, curve.getPsn(), curve.getStartDateTime(), curve.getEndDateTime());
        Map mapList = new HashMap();
        //查询曲线
        List<CurveVo> list = curveMapper.selectCurveVoList(curve);
        //查询最大最小平均值
        Map maps = curveMapper.selectMinAdnMax(curve);
        mapList.put("list",list);
        mapList.put("min",maps.get("small"));
        mapList.put("max",maps.get("big"));
        mapList.put("average",maps.get("ag"));
        if (list.size() > 0) {
            redisCache.setCacheMap(key, mapList);
            //使用 删除缓存
            redisCache.expire(key, 2, TimeUnit.MINUTES);
        }
        return mapList;
    }

  /**
     * 查询【查询曲线】列表  多条返回
     * 分钟级别
     *
     * @param curve 【查询曲线】
     * @return 【查询曲线】集合
     */
    @Override
    public List<CurveManyVo> selectCurveManyVoList(Curve curve) {
        String[] items = curve.getPsn().split(",");
        List<CurveManyVo> curveManyVos = new ArrayList<>();
        CurveManyVo curveManyVo ;
        for (String s :items){
            curve.setPsn(s);
            curveManyVo = new CurveManyVo();
            curveManyVo.setCurveVos(curveMapper.selectCurveVoList(curve));
            curveManyVo.setPsn(s);
            curveManyVos.add(curveManyVo);
        }
        return curveManyVos;
    }



    /**
     * 设置cache key
     *
     * @param configKey 参数键
     * @return 缓存键key
     */
    private String getCacheDsnKey(String configKey, String psn, String startDateTime, String endDateTime) {
        return configKey + psn + startDateTime.replaceAll(":", "_") + "_" + endDateTime.replaceAll(":", "_");
    }

}

8. Controller类

/**
 * @author WXY
 * @date 2023/2/24 15:28
 */
@RestController
@RequestMapping("/xx/curvemessage")
public class CurveController extends BaseController {

    @Autowired
    private ICurveService iCurveService;


    /**
     * 查询单条【曲线日志】列表  按秒级 来查询
     * 需要查询出来 最大值最小值 还有平均值
     */
    @GetMapping("/listMinMax")
    public AjaxResult listMinMax(Curve curve) {
        curve.setTable(TABLE + curve.getOutsideTime());
       if (StringUtils.isNotEmpty(curve.getPsn())&&StringUtils.isNotEmpty(curve.getStartDateTime())&&StringUtils.isNotEmpty(curve.getEndDateTime())){
           //查询之后缓存  缓存5分钟  当再次请求此接口在替换掉缓存的值  方便下载功能
           Map list = iCurveService.selectMinAdnMax(curve);
           return AjaxResult.success(list);
       }else {
           return AjaxResult.success("psn或者时间丢失");
       }
    }


    /**
     * 查询单条【曲线日志】列表  按秒级 来查询
     * 没有最大最小值和平均值
     */
    @GetMapping("/list")
    public AjaxResult list(Curve curve) {
        curve.setTable(TABLE + curve.getOutsideTime());
        if (StringUtils.isNotEmpty(curve.getPsn())&&StringUtils.isNotEmpty(curve.getStartDateTime())&&StringUtils.isNotEmpty(curve.getEndDateTime())){
            //查询之后缓存  缓存5分钟  当再次请求此接口在替换掉缓存的值  方便下载功能
            List<CurveVo> list = iCurveService.selectCurveVoList(curve);
            return AjaxResult.success(list);
        }else {
            return AjaxResult.success("psn或者时间丢失");
        }
    }

    /**
     * 查询多条【曲线日志】列表
     */
    @GetMapping("/listCurveMany")
    public AjaxResult listCurveMany(Curve curve) {
        Long start = System.currentTimeMillis();
        if (StringUtils.isNotEmpty(curve.getPsn())&&StringUtils.isNotEmpty(curve.getStartDateTime())&&StringUtils.isNotEmpty(curve.getEndDateTime())){
            curve.setTable(TABLE + curve.getOutsideTime());
            List<CurveManyVo> list = iCurveService.selectCurveManyVoList(curve);
            Long end = System.currentTimeMillis();
            long time = end - start;
            //debug
            System.out.println("查询listCurveMany/" + time + "毫秒");
            return AjaxResult.success(list);
        }else {
            return AjaxResult.success("psn或者时间丢失");
        }
    }
}

晚点在写 没有用若依框架 怎么搭建主从数据库

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/398577.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

Homekit智能家居产品---智能吸顶灯

买灯要看什么因素 好灯具的灯光可以说是家居的“魔术师”&#xff0c;除了实用的照明功能外&#xff0c;对细节的把控也非常到位。那么该如何选到一款各方面合适的灯呢&#xff1f; 照度 可以简单理解为清晰度&#xff0c;复杂点套公式来说照度光通量&#xff08;亮度&#x…

5款小巧好用的电脑软件,让你的工作生活更加高效!

不得不说良心好软件让大家好评连连&#xff0c;爱不释手&#xff0c;不像某些软件自带广告弹窗。这期就由我给大家安利几款电脑中的得力助手&#xff0c;看看你都用过几个&#xff1f; 1.桌面管理神器——Coodesker Coodesker是一款免费小巧、无广告&#xff0c;功能简单的桌…

【Redis】哨兵机制(三)

目录 3.Redis哨兵 3.1.哨兵原理 3.1.1.集群结构和作用 3.1.2.集群监控原理 3.1.3.集群故障恢复原理 3.1.4.小结 3.2.搭建哨兵集群 3.3.RedisTemplate 3.3.1.导入Demo工程 3.3.2.引入依赖 3.3.3.配置Redis地址 3.3.4.配置读写分离 3.Redis哨兵 Redis提供了哨兵&am…

Spring Cloud Gateway学习

文章大纲 为什么需要网关&#xff1f; 传统的单体架构只有一个服务开放给客户端调用&#xff0c;但是在微服务架构体系中是将一个系统拆分成多个微服务&#xff0c;那么作为客户端如何去调用这些微服务呢&#xff1f;如果没有网关的存在&#xff0c;就只能在本地记录每个微服务…

彻底关闭Windows10更新!!

以下四个步骤都需要执行。 一、禁用Windows Update服务 1、同时按下键盘 Win R&#xff0c;然后输入 services.msc &#xff0c;点击确定。 2、找到 Windows Update 这一项&#xff0c;并双击打开。 3、双击打开它&#xff0c;点击 停止&#xff0c;把启动类型选为 禁用&…

SpringBoot+@Async注解-异步调用

编程开发里&#xff0c;使用java异步执行方法可以让程序同时处理多个请求业务&#xff0c;提升吞吐量来缩短业务的执行时间&#xff0c;在springboot的程序应用中&#xff0c;提供了Async注解来实现异步执行方法。在业务开发中&#xff0c;有些时候是不需要立即返回业务的处理结…

前端代码质量-圈复杂度原理和实践

1. 导读 你们是否也有过下面的想法&#xff1f; 重构一个项目还不如新开发一个项目…这代码是谁写的&#xff0c;我真想… 你们的项目中是否也存在下面的问题&#xff1f; 单个项目也越来越庞大&#xff0c;团队成员代码风格不一致&#xff0c;无法对整体的代码质量做全面的…

【LeetCode】剑指 Offer 25. 合并两个排序的链表 p145 -- Java Version

题目链接&#xff1a;https://leetcode.cn/problems/he-bing-liang-ge-pai-xu-de-lian-biao-lcof/ 1. 题目介绍&#xff08;25. 合并两个排序的链表&#xff09; 输入两个递增排序的链表&#xff0c;合并这两个链表并使新链表中的节点仍然是递增排序的。 【测试用例】&#xf…

软件测试分类知识分享,第三方软件测试机构收费贵不贵?

软件测试可以很好的检验软件产品的质量以及规避产品上线之后可能会发生的错误&#xff0c;随着技术的发展&#xff0c;软件测试已经是一个完整且体系庞大的测试活动&#xff0c;不同的测试领域有着不同的测试方法、技术与名称&#xff0c;那么具体有哪些分类呢? 一、软件测试…

centos7部署KVM虚拟化

目录 centos7部署KVM虚拟化平台 1、新建一台虚拟机 2、系统内的操作 1、修改主机名 2、挂载镜像光盘 3、ssh优化 4、设置本地yum仓库 5、关闭防火墙&#xff0c;selinux 3、安装KVM 4、设置KVM网络 5、KVM部署与管理 6、使用虚拟系统管理器管理虚拟机 创建存储池 …

[曾经沧海难为水]两数求和

本来可以面试成功就差HR面试了&#xff0c;现在给我说恒英也要机试题了。我现在肝机试题吧&#xff01;大环境就是这&#xff0c;记录两周一个机试学习过程V1&#xff1a;自己写的暴力法V2&#xff1a;暴力法2:通过python的**str in list**方式逐个遍历&#xff0c;虽然代码看似…

什么叫GPC爬虫池?

什么叫GPC爬虫池&#xff1f; 答案是&#xff1a;全称光算谷歌爬虫池。 GPC爬虫池是一个深度研究谷歌SEO规律算法而创造的一种吸引谷歌爬虫的技术手段。 主要实现原理是通过建设庞大的站群系统&#xff0c;复杂的内链&#xff0c;外链结构体系&#xff0c;起到吸引谷歌爬虫&…

NetworkMiner网络取证分析工具(26)

预备知识 NetworkMiner是一款windows平台下开放源代码的网络取证分析工具&#xff0c;同时也是一款比较好的协议分析工具&#xff0c;它通过数据包嗅探或解析PCAP 文件能够检测操作系统&#xff0c;主机名和网络主机开放的端口。 除了能够进行基本的数据包抓取分析N…

剑指 Offer day5, day6

剑指 Offer day5&#xff0c; day6 二分查找和二叉树的题目 剑指 Offer 04. 二维数组中的查找 剑指 Offer 04. 二维数组中的查找 - 力扣&#xff08;Leetcode&#xff09; 依然是利用特殊的数据状况改进查找的速度&#xff0c;注意边界条件。 题解这个类比二叉树的思路非常…

第五章:C语言数据结构与算法之双向带头循环链表

系列文章目录 文章目录系列文章目录前言一、哨兵位的头节点二、双向链表的结点三、接口函数的实现1、创建结点2、初始化3、尾插与尾删4、头插与头删5、打印6、查找7、随机插入与随机删除8、判空、长度与销毁四、顺序表和链表的对比总结前言 一般题目给的单链表是无头单向非循环…

GCC编译器编译C/C++程序(一步完成、分步完成)

以下内容源于C语言中文网的学习与整理&#xff0c;非原创&#xff0c;如有侵权请告知删除。 一、编译的流程 编译C/C 程序&#xff0c;是指将C/C源代码转变为可执行程序。 这需要经历4个过程&#xff1a;预处理&#xff08;Preprocessing&#xff09;、编译&#xff08;Compi…

一次线上事故排查

问题3月1日监控系统监测到某子系统所在机器Cpu突然飙升。排查系统首先登录对应系统的机器&#xff0c;top查看机器信息&#xff0c;显示当前cpu已经到了800%top 显示800%根据top的pid查看对应服务&#xff0c;查看服务子进程排查子线程&#xff0c;发现子线程有8个都100%了&…

ESP32通过HTTP及SNTP同步网络时间

1、获取毫秒级时间 和普通系统函数相同 int get_sys_time_ms(void) {struct timeval tv_now;gettimeofday(&tv_now, NULL);int64_t time_us (int64_t)tv_now.tv_sec * 1000000L (int64_t)tv_now.tv_usec;return (int)(time_us/1000); } 2、延时毫秒级时间 void my_del…

【数据分析师求职面试指南】必备编程技能整理之Hive SQL必备用法

文章目录熟悉Python懂R语言掌握SQL大数据基础数据库常用类型多表查询更多聚合函数distinctcase when窗口函数动态更新一行变多行调优内容整理自《拿下offer 数据分析师求职面试指南》—徐粼著 第四章编程技能考查熟悉Python 懂R语言 掌握SQL 大数据基础 Hive时Hadoop的一个…

C++基础了解-10-C++ 判断

C 判断 一、C 判断 判断结构要求程序员指定一个或多个要评估或测试的条件&#xff0c;以及条件为真时要执行的语句&#xff08;必需的&#xff09;和条件为假时要执行的语句&#xff08;可选的&#xff09;。 下面是大多数编程语言中典型的判断结构的一般形式&#xff1a; …