如何将Mybatis连接到ClickHouse

网友投稿 393 2023-01-26

如何将Mybatis连接到ClickHouse

场景

最近在做数据分析项目,里面有这样一个业务:把匹配的数据打上标签,放到新的索引中。

数据量:累计亿级的数据

使用场景:可能会单次查询大量的数据,但不会设置复杂的条件,且这些数据不会被再次修改

原来使用的数据库:ElasticSearch

问题:上面也说了我这里打上标记后,这些数据几乎不会再修改了。ES 是一个全文检索引擎,更适用于进行大量文本检索的情况。这里与我上面的使用场景就不太匹配了。

技术选型的考虑:改用战斗民族开发的 ClickHouse,它适用于 OLAP 也就是数据分析的场景,当数据写入后,通过不同维度不断挖掘、分析,发现其中的商业价值。ClickHouse 适用于读远大于写的情况。

此外,相比ES,ClickHouse 占用的硬盘空间更小,也有利于降低运维成本。

下面是我在尝试接入 ClickHouse 时的一些实践,以及关于 ClickHouse数组类型转换问题的解决方案。

关于 ClickHouse 更详细的知识参考:https://zhuanlan.zhihu.com/p/98135840

示例代码已经上传到了 Git,目前更新第 28 节:https://github.com/laolunsi/spring-boot-examples/

Mybatis + ClickHouse

以前一直用 Mybatis 去操作 mysql,其实 Mybatis 还可以操作 ClickHouse,这里用 Druid 进行连接管理。

maven 配置

com.alibaba

druid

1.2.5

ru.yandex.clickhouse

clickhouse-jdbc

0.2.6

org.mybatis.spring.boot

mybatis-spring-boot-starter

2.1.3

配置文件:

spring:

datasource:

type: com.alibaba.druid.pool.DruidDataSource

# 注意这里是自定义的配置,通过 JdbcParamConfig 来加载配置到 Spring 中

# 然后由 DruidConfig 来配置数据源

click:

driverClassName: ru.yandex.clickhouse.ClickHouseDriver

url: jdbc:clickhouse://127.0.0.1:8123/test # ip:port/database

userNahttp://me: default

password: default # 按照自己连接的 clickhouse 数据库来

initialSize: 10

maxActive: 100

minIdle: 10

maxWait: 6000

validationQuery: SELECT 1

加载配置项的类:

@Component

@ConfigurationProperties(prefix = "spring.datasource.click")

public class JdbcParamConfig {

private String userName;

private String password;

private String driverClassName ;

private String url ;

private Integer initialSize ;

private Integer maxActive ;

private Integer minIdle ;

private Integer maxWait ;

private String validationQuery;

// ignore getters and setters

}

配置 Druid:

@Configuration

@MapperScan(basePackages = {

"com.aegis.analysis.clickhousestorage.dao"

})

public class DruidConfig {

@Resource

private JdbcParamConfig jdbcParamConfig ;

@Bean(name = "clickDataSource")

public DataSource dataSource() throws ClassNotFoundException {

Class classes = Class.forName("com.alibaba.druid.pool.DruidDataSource");

DruidDataSource dataSource = (DruidDataSource) DataSourceBuilder

.create()

.driverClassName(jdbcParamConfig.getDriverClassName())

.type(classes)

.url(jdbcParamConfig.getUrl())

.username(jdbcParamConfig.getUserName())

.password(jdbcParamConfig.getPassword())

.build();

dataSource.setMaxWait(jdbcParamConfig.getMaxWait());

dataSource.setValidationQuery(jdbcParamConfig.getValidationQuery());

return dataSource;

}

@Bean

public SqlSessionFactory clickHouseSqlSessionFactoryBean() throws Exception {

SqlSessionFactoryBean factory = new SqlSessionFactoryBean();

factory.setDataSource(dataSource());

// 实体 model的 路径 比如 com.order.model

factory.setTypeAliasesPackage("com.example.clickhousedemo.model");

//添加XML目录

ResourcePatternResolver resolver = new PathMatchingResourcePatternResolver();

factory.setMapperLocations(resolver.getResources("classpath:mapper/*.xml"));

//开启驼峰命名转换

factory.getObject().getConfiguration().setMapUnderscoreToCamelCase(true);

return factory.getObject();

}

}

定义一个 UserInfo 类,建表语句如下:

CREATE TABLE test.user (

`id` Int16,

`name` String,

`score` Float32,

`score2` Float64,

`state` Int8,

`createTime` DateTime,

`ranks` Array(UInt8)

) ENGINE = MergeTree() ORDER BY id;

实体类:

public class UserInfo {

private Integer id; // int16

private String name; // String

private Float score; // float16

private Double score2; // float32

private Boolean state; // int8

private Date createTime; // datetime

private Integer[] ranks; // Array - Array 类型需要进行类型转换

// 具体转换方法与配置参考 ClickArrayToIntHandler 类与 UserMapper.xml 中关于查询和插入时 ranks 字段的配置

// ignore getters and setters

}

DAO 和 Mapper 文件就按照连接 MYSQL 时的写法一样。

这里有个需要注意的点,ClickHouse 有个 Array 类型,可以用来存数组,就像 ES 一样。问题是类型转换需要自己定义。网上一些资料仅列出了基本类型的场景,我自己实现了一个转换器,可以参考一下:

/**

* java Int 数组与 ClockHouse Array Int 转换器

* @version 1.0

* @since 2019/11/14 9:59

*/

public class ClickArrayToIntHandler extends BaseTypeHandler {

@Override

public void setNonNullParameter(PreparedStatement preparedStatement, int i, Integer[] integers, JdbcType jdbcType) throws SQLException {

preparedStatement.setObject(i, integers);

}

@Override

public Integer[] getNullableResult(ResultSet resultSet, String s) throws SQLException {

Object obj = resultSet.getObject(s);

return parseClickHouseArrayToInt(obj);

}

@Override

public Integer[] getNullableResult(ResultSet resultSet, int i) throws SQLException {

Object obj = resultSet.getObject(i);

return parseClickHouseArrayToInt(obj);

}

@Override

public Integer[] getNullableResult(CallableStatement callableStatement, int i) throws SQLException {

Object obj = callableStatement.getObject(i);

return parseClickHouseArrayToInt(obj);

}

private Integer[] parseClickHouseArrayToInt(Object obj) {

if (obj instanceof ClickHouseArray) {

int[] res = new int[0];

try {

res = (int[]) ((ClickHouseArray) obj).getArray();

} catch (SQLException ex) {

ex.printStackTrace();

}

if (res != null && res.length > 0) {

Integer[] resI = new Integer[res.length];

for (int i = 0; i < res.length; i++) {

resI[i] = res[i];

}

return resI;

}

}

return new Integer[0];

}

}

DAO.xml 也给一个示例:

*

INSERT INTO user

(id,name, score, score2, state, createTime, ranks)

VALUES

(#{id},#{name}, #{score}, #{score2}, #{state}, #{createTime}, #{ranks, jdbcType=ARRAY,

typeHandler=com.example.clickhousedemo.dao.ClickArrayToIntHandler})

select

from user

where id = #{id}

limit 1

select

from user

具体代码可以去我的 Git 仓库里查看,还有 SpringBoot 整合其他中间件技术的示例,欢迎 Star!

https://github.com/laolunsi/spring-boot-examples

以上就是如何将Mybatis连接到ClickHouse的详细内容,更多关于Mybatis连接到ClickHouse的资料请关注我们其它相关文章!

版权声明:本文内容由网络用户投稿,版权归原作者所有,本站不拥有其著作权,亦不承担相应法律责任。如果您发现本站中有涉嫌抄袭或描述失实的内容,请联系我们jiasou666@gmail.com 处理,核实后本网站将在24小时内删除侵权内容。

上一篇:SpringBoot整合RabbitMQ, 实现生产者与消费者的功能
下一篇:什么是开放api接口(开放api接口什么意思)
相关文章

 发表评论

暂时没有评论,来抢沙发吧~