ClickHouse数据库之JPA篇

标签: Clickhouse 分类: 数据库 创建时间:2020-08-06 05:23:04 更新时间:2023-10-20 11:23:25

clickhouse支持jdbc连接,也支持http,还支持Python等,这篇文章尝试使用SpringBoot Jpa连接和操作ClickHouse数据库。这里的示例使用的是多数据源的形式,所以需要自定义Configuration。

1.引入依赖

1
2
3
4
5
6
<!--clickhouse-->
<dependency>
<groupId>ru.yandex.clickhouse</groupId>
<artifactId>clickhouse-jdbc</artifactId>
<version>0.2.4</version>
</dependency>

2.修改application

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
spring:
jackson:
time-zone: GMT+8
mvc:
throw-exception-if-no-handler-found: true
resources:
add-mappings: false
datasource:
third:
driver-class-name: ru.yandex.clickhouse.ClickHouseDriver
jdbc-url: jdbc:clickhouse://192.168.1.90:8123/databasename
username: xxx
password: xxx
connection-timeout: 20000
maximum-pool-size: 5
jpa:
hibernate:
naming:
implicit-strategy: org.hibernate.boot.model.naming.ImplicitNamingStrategyJpaCompliantImpl
physical-strategy: org.hibernate.boot.model.naming.PhysicalNamingStrategyStandardImpl
show-sql: true

其中的databasename是你自己数据库的名字。

3.创建实体

1
2
3
4
5
6
7
8
9
10
11
12
13
package com.proheng.gis.clickhouseEntity;
import javax.persistence.*;
@Entity
@Table(name="pipeHeatAnalyse")
public class PipeHeatAnalyse {
@Id
@GeneratedValue(strategy = GenerationType.AUTO)
private Long id;

private String calcTable; // 分析表格

// 省略get/set
}

4.编写resposity

1
2
3
4
5
6
7
package com.proheng.gis.clickhouseReposities;

import com.proheng.gis.clickhouseEntity.PipeHeatAnalyse;
import org.springframework.data.jpa.repository.JpaRepository;

public interface PipeHeatAnalyseRepository extends JpaRepository<PipeHeatAnalyse,Long> {
}

5.编写JpaConfiguration

其中的实体和Reposities的位置要换成自己的。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
@Configuration
@EntityScan(basePackages = "com.proheng.gis.clickhouseEntity")
//1、实体扫描
//2、实体管理ref
//3、事务管理
@EnableJpaRepositories(
basePackages = "com.proheng.gis.clickhouseReposities",
entityManagerFactoryRef = "thirdEntityManagerFactoryBean",
transactionManagerRef = "thirdTransactionManager")
@EnableTransactionManagement
public class JpaThirdConfiguration {

/**
* 第二个数据源
* @return
*/
@Bean(name = "dataSourceThird")
@ConfigurationProperties(prefix = "spring.datasource.third")
public DataSource dataSourceThird() {
return DataSourceBuilder.create().build();
}

//第三个数据源,必须加Qualifier
@Autowired
@Qualifier("dataSourceThird")
private DataSource dataSource;

//jpa其他参数配置
@Autowired
private JpaProperties jpaProperties;

//实体管理工厂builder
@Autowired
private EntityManagerFactoryBuilder factoryBuilder;

/**
* 配置第二个实体管理工厂的bean
* @return
*/
@Bean(name = "thirdEntityManagerFactoryBean")
public LocalContainerEntityManagerFactoryBean entityManagerFactoryBean() {
return factoryBuilder.dataSource(dataSource)
.properties(getVendorProperties())
.packages("com.proheng.gis.clickhouseEntity")
.persistenceUnit("thirdPersistenceUnit")
.build();
}
@Autowired
private HibernateProperties hibernateProperties;

private Map<String, Object> getVendorProperties() {
Map<String,String> properties=jpaProperties.getProperties();

// 为了解决分页查询时的错误
// 因为使用的是clicakhouse数据库,但是没有clickhouse数据库的方言,但是进行分页查询时候,就需要设置一个方言
// 又因为MySQLDialect的方言差不多,于是就设置了MySQLDialect
properties.put("hibernate.dialect", "org.hibernate.dialect.MySQLDialect");

return hibernateProperties.determineHibernateProperties(
properties, new HibernateSettings());
}
/**
* EntityManager不过解释,用过jpa的应该都了解
* @return
*/
@Bean(name = "thirdEntityManager")
public EntityManager entityManager() {
return entityManagerFactoryBean().getObject().createEntityManager();
}

/**
* jpa事务管理
* @return
*/
@Bean(name = "thirdTransactionManager")
public JpaTransactionManager transactionManager() {
JpaTransactionManager jpaTransactionManager = new JpaTransactionManager();
jpaTransactionManager.setEntityManagerFactory(entityManagerFactoryBean().getObject());
return jpaTransactionManager;
}
}

注意
在执行分页查询的时候,Hibernate默认的使用的是ROW_NUMBER() OVER的方式,但是clickhouse不支持,就可能会出错,所以需要设置一个方言Dialect,我上面设置了MySQLDialect

参考文章:
1.数据库属性hibernate.dialect的设置 (方言列表)

6.使用

有些地方还需要自己实现@Service层,但是我这里的比较简单,就没有实现@Service层。

1
2
3
4
5
6
7
8
9
10
11
12
13
@RestController
@RequestMapping(value = "/api")
public class PipeHeatAnalysis {
@Autowired
private PipeHeatAnalyseRepository pipeHeatAnalyseRepository;

@RequestMapping("/getPipeHeatAnalysis")
public List<PipeHeatAnalyse> getPipeHeatAnalysis(){
List<PipeHeatAnalyse> pipeHeatAnalyses=pipeHeatAnalyseRepository.findAll();

return pipeHeatAnalyses;
}
}

7.结果

小额赞助
本人提供免费与付费咨询服务,感谢您的支持!赞助请发邮件通知,方便公布您的善意!
**光 3.01 元
Sun 3.00 元
bibichuan 3.00 元
微信公众号
广告位
诚心邀请广大金主爸爸洽谈合作
每日一省
isNaN 和 Number.isNaN 函数的区别?

1.函数 isNaN 接收参数后,会尝试将这个参数转换为数值,任何不能被转换为数值的的值都会返回 true,因此非数字值传入也会返回 true ,会影响 NaN 的判断。

2.函数 Number.isNaN 会首先判断传入参数是否为数字,如果是数字再继续判断是否为 NaN ,不会进行数据类型的转换,这种方法对于 NaN 的判断更为准确。

每日二省
为什么0.1+0.2 ! == 0.3,如何让其相等?

一个直接的解决方法就是设置一个误差范围,通常称为“机器精度”。对JavaScript来说,这个值通常为2-52,在ES6中,提供了Number.EPSILON属性,而它的值就是2-52,只要判断0.1+0.2-0.3是否小于Number.EPSILON,如果小于,就可以判断为0.1+0.2 ===0.3。

每日三省
== 操作符的强制类型转换规则?

1.首先会判断两者类型是否**相同,**相同的话就比较两者的大小。

2.类型不相同的话,就会进行类型转换。

3.会先判断是否在对比 null 和 undefined,是的话就会返回 true。

4.判断两者类型是否为 string 和 number,是的话就会将字符串转换为 number。

5.判断其中一方是否为 boolean,是的话就会把 boolean 转为 number 再进行判断。

6.判断其中一方是否为 object 且另一方为 string、number 或者 symbol,是的话就会把 object 转为原始类型再进行判断。

每日英语
Happiness is time precipitation, smile is the lonely sad.
幸福是年华的沉淀,微笑是寂寞的悲伤。