前言
上一章节讲解在阿里云ECS centos服务器上安装ClickHouse。
这一章节我们在Springboot里集成Mybatis-plus、ClickHouse。
环境:JDK8 + Springboot 2.6.13 + ClickHouse
1、构建JDK8 + Springboot 2.6.13项目
JDK8 + Springboot 2.x基本上都可以,保险起见,2.5-2.7左右最好。
1.1、修改Server URL,支持Java8
在Idea里创建一个Springboot项目,首先修改Server URL,默认的Server URL已经不支持JDK8。
1.2、 选择Springboot 版本、选择加载的依赖包
1.3、查看pom.xml文件
构建完成之后,就会生成一个Springboot项目,文件里最主要是pom.xml文件。
1.4、检查项目结构
1.4.1、检查项目设置
与我们的项目里选择的JDK8保持一致
1.4.2、检查模块
检查项目结构,语言级别、Sources、Resources、Test Resources等。
1.5、检查项目配置
检查项目的Settings。
1.5.1、配置Maven环境
(JDK8 对应的是3.3 - 3.9等,一般使用3.6、3.8最佳)
1.5.2、检查Java编译配置
检查Java编译配置,1.8、8都可以,代表使用java8编译Java文件。
2、集成Mybatis-plus、ClickHouse
2.1、加载Mybatis-plus、ClickHouse依赖包
在pom.xml文件里加载Mybatis-plus、ClickHouse依赖包。
顺道把fastjson也加入进去。
<dependency> <groupId>ru.yandex.clickhouse</groupId> <artifactId>clickhouse-jdbc</artifactId> <version>0.1.53</version> </dependency> <!--Mybatis-plus ORM--> <dependency> <groupId>com.baomidou</groupId> <artifactId>mybatis-plus-boot-starter</artifactId> <version>3.5.1</version> </dependency> <!-- https://mvnrepository.com/artifact/com.alibaba/fastjson --> <dependency> <groupId>com.alibaba</groupId> <artifactId>fastjson</artifactId> <version>2.0.33</version> </dependency>
2.2、修改配置文件
把默认的application.properties文件修改为 application.yaml文件
spring: application: name: clickhouse-project datasource: type: com.zaxxer.hikari.HikariDataSource url: jdbc:clickhouse://clickhouse远程主机:8123/default driver-class-name: ru.yandex.clickhouse.ClickHouseDriver username: default password: mybatis-plus: # 搜索指定包别名 type-aliases-package: com.xique.springbootclick.entity configuration: map-underscore-to-camel-case: true #开启驼峰命名 cache-enabled: false #开启二级缓存 log-impl: org.apache.ibatis.logging.stdout.StdOutImpl # 控制台日志 check-config-location: true # 检查xml是否存在 type-enums-package: com.gton.enumPackage #通用枚举开启 global-config: db-config: logic-not-delete-value: 1 logic-delete-field: isDel logic-delete-value: 0 table-prefix: t_ server: port: 18123
3、在clickhouse里添加表
创建一张商品表,skuId、url、image、country、name、price、freight等字段。
CREATE TABLE default.t_product ( `skuId` String, `url` String, `image` String, `country` String, `name` String, `price` String, `freight` String ) ENGINE = SummingMergeTree PARTITION BY country ORDER BY skuId SETTINGS index_granularity = 8192
数据库表创建成功,使用show tables命令,就可以看到我们创建的表了。
4、在Springboot项目里创建商品表的操作类
4.1、添加雪花ID实现
我们这次采用雪花ID生成商品SkuId,所以添加雪花ID实现
public class SnowflakeIdWorker { /** * 开始时间截 (2015-01-01) */ private final long twepoch = 1420041600000L; /** * 机器id所占的位数 */ private final long workerIdBits = 5L; /** * 数据标识id所占的位数 */ private final long datacenterIdBits = 5L; /** * 支持的最大机器id,结果是31 (这个移位算法可以很快的计算出几位二进制数所能表示的最大十进制数) */ private final long maxWorkerId = -1L ^ (-1L << workerIdBits); /** * 支持的最大数据标识id,结果是31 */ private final long maxDatacenterId = -1L ^ (-1L << datacenterIdBits); /** * 序列在id中占的位数 */ private final long sequenceBits = 12L; /** * 机器ID向左移12位 */ private final long workerIdShift = sequenceBits; /** * 数据标识id向左移17位(12+5) */ private final long datacenterIdShift = sequenceBits + workerIdBits; /** * 时间截向左移22位(5+5+12) */ private final long timestampLeftShift = sequenceBits + workerIdBits + datacenterIdBits; /** * 生成序列的掩码,这里为4095 (0b111111111111=0xfff=4095) */ private final long sequenceMask = -1L ^ (-1L << sequenceBits); /** * 工作机器ID(0~31) */ private long workerId; /** * 数据中心ID(0~31) */ private long datacenterId; /** * 毫秒内序列(0~4095) */ private long sequence = 0L; /** * 上次生成ID的时间截 */ private long lastTimestamp = -1L; /** * 构造函数 * @param workerId 工作ID (0~31) * @param datacenterId 数据中心ID (0~31) */ public SnowflakeIdWorker(long workerId, long datacenterId) { if (workerId > maxWorkerId || workerId < 0) { throw new IllegalArgumentException(String.format("worker Id can't be greater than %d or less than 0", maxWorkerId)); } if (datacenterId > maxDatacenterId || datacenterId < 0) { throw new IllegalArgumentException(String.format("datacenter Id can't be greater than %d or less than 0", maxDatacenterId)); } this.workerId = workerId; this.datacenterId = datacenterId; } /** * 获得下一个ID (该方法是线程安全的) * @return SnowflakeId */ public synchronized long nextId() { long timestamp = timeGen(); // 如果当前时间小于上一次ID生成的时间戳,说明系统时钟回退过这个时候应当抛出异常 if (timestamp < lastTimestamp) { throw new RuntimeException( String.format("Clock moved backwards. Refusing to generate id for %d milliseconds", lastTimestamp - timestamp)); } // 如果是同一时间生成的,则进行毫秒内序列 if (lastTimestamp == timestamp) { sequence = (sequence + 1) & sequenceMask; // 毫秒内序列溢出 if (sequence == 0) { //阻塞到下一个毫秒,获得新的时间戳 timestamp = tilNextMillis(lastTimestamp); } } // 时间戳改变,毫秒内序列重置 else { sequence = 0L; } // 上次生成ID的时间截 lastTimestamp = timestamp; // 移位并通过或运算拼到一起组成64位的ID return ((timestamp - twepoch) << timestampLeftShift) // | (datacenterId << datacenterIdShift) // | (workerId << workerIdShift) // | sequence; } /** * 阻塞到下一个毫秒,直到获得新的时间戳 * @param lastTimestamp 上次生成ID的时间截 * @return 当前时间戳 */ protected long tilNextMillis(long lastTimestamp) { long timestamp = timeGen(); while (timestamp <= lastTimestamp) { timestamp = timeGen(); } return timestamp; } /** * 返回以毫秒为单位的当前时间 * @return 当前时间(毫秒) */ protected long timeGen() { return System.currentTimeMillis(); } }
通过Common类去调用
public class Common { public static volatile SnowflakeIdWorker idWorker = null; public static synchronized SnowflakeIdWorker getIdWorker() { if (null == idWorker) { idWorker = new SnowflakeIdWorker(0, 0); } return idWorker; } }
4.2、添加Mybatis-plus写法的表操作
可以使用Mybatis代码生成工具,逆向ClickHouse数据库生成代码,并复制到项目里面,省时省力。
不会的同学可以去学习我的【Springboot】专栏。
5、测试
增加单元测试。
package com.qhkj.clickhousedemo; import com.alibaba.fastjson.JSON; import com.qhkj.clickhousedemo.constant.Common; import com.qhkj.clickhousedemo.entity.Product; import com.qhkj.clickhousedemo.service.ProductService; import lombok.extern.slf4j.Slf4j; import org.junit.jupiter.api.Test; import org.springframework.boot.test.context.SpringBootTest; import javax.annotation.Resource; import java.util.List; @Slf4j @SpringBootTest public class ProductTest { @Resource private ProductService productService; @Test void saveProduct() { Product product = Product.builder() .skuId(String.valueOf(Common.getIdWorker().nextId())) .url("http://xxx.com/skuid=xxxx") .country("EN") .image("http://image.xxx.com/skuid=xxxx") .name("DIABLO 4 GOLD SEASON 5") .price("275美元") .freight("15美元运费") .build(); productService.save(product); log.info("商品信息保存成功"); } @Test void selectAll() { List<Product> productList = productService.selectAll(); log.info("productList:{}", JSON.toJSONString(productList)); } }
5.1、新增数据
构造一个商品类,新增一条数据并执行
5.2、查询数据
查询所有数据。
结尾
本章节,讲解Springboot + mybatis-plus 集成ClickHouse,实现增加数据、查询数据。
下一章节,我们在项目里集成RabbitMq,使用消息队列来接收数据,并存储到ClickHouse。
数据来源我们另外构造一个系统,使用Springboot + Jsoup解析ebay网数据,去获取耳机、显卡、iPhone等类目的热卖商品,使用RabbitMq发送数据。