💠
💠 2024-10-21 22:05:55
数据库模块
Spring Data
多数据源配置
为什么要有多数据源?
- 业务发展和划分拆解导致业务库被拆分(例如用户库,订单库),或者异构数据源支撑(订单库MySQL,订单快照库ES)
Spring Boot多数据源配置与使用
连接池
c3p0
Github
druid
druid连接池引起的线程blocked驱动改名引起的连锁反应
常见配置项
- com.alibaba.druid.pool.DruidDataSource#configFromPropety 环境变量 可配置项
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
|
# 初始连接数
initialSize: 6
# 最小连接池数量
minIdle: 6
# 最大连接池数量
maxActive: 200
# 配置获取连接等待超时的时间
maxWait: 60000
# 驱逐连接:配置间隔多久才进行一次检测,检测需要关闭的空闲连接,单位是毫秒
timeBetweenEvictionRunsMillis: 60000
# 驱逐连接:配置一个连接在池中最小生存的时间,单位是毫秒
minEvictableIdleTimeMillis: 200000
# 驱逐连接:配置一个连接在池中最大生存的时间,单位是毫秒
maxEvictableIdleTimeMillis: 280000
# 心跳保活
keepAlive: true
# 心跳保活间隔,keepAlive开启才生效
keepAliveBetweenTimeMillis: 40000
# 配置检测连接是否有效 创建连接和心跳保活时执行
validationQuery: SELECT 1
# 建议配置为true,不影响性能,并且保证安全性。申请连接的时候检测,如果空闲时间大于 timeBetweenEvictionRunsMillis ,执行validationQuery检测连接是否有效
testWhileIdle: true
# 申请连接时执行validationQuery检测连接是否有效 性能影响明显
testOnBorrow: false
# 归还连接时执行validationQuery检测连接是否有效 性能影响明显
testOnReturn: false
|
validationQuery执行场景
周期检查 keepAlive
获取连接时 闲置很久的连接触发检查
创建连接时的检查
Druid连接检查机制
com.alibaba.druid.pool.DruidDataSource#createAndStartDestroyThread
定时调度或单线程方式 周期性 检查连接
com.alibaba.druid.pool.DruidDataSource#shrink(boolean, boolean)
keepAlive保活,补充新连接,关闭连接(异常,空闲超时)
com.alibaba.druid.pool.ValidConnectionChecker
检查连接可用,注意MySQL PG都有协议层的ping方式,更省资源(类似ws协议中的Ping报文),其他数据库一般是配置校验SQL为 select 1
HikariCP
HikariCP
Relational Database
JPA
连接池:1.x 默认是tomcat-jdbc连接池 2.x 是 HikariPool
参考: spring boot2 整合(二)JPA
Configuration
Official Doc
ddl-auto
Jpa数据分页
参考博客
- 分页 page 从0开始 size是个数 sort可以不需要(如果本来就是id排序就没必要了)
- 原理就是 预编译SQL然后查询总数,然后再执行 必须有两条SQL执行
- 查询的结果不包含实体的id属性
原生SQL
- 涉及到数据的修改,就要加上前两个前缀,查询就直接写Query注解即可
1
2
3
|
@Modifying
@Transactional
@Query(value = "update a set b=?1", nativeQuery = true)
|
Mysql
1
2
3
|
compile('org.springframework.boot:spring-boot-starter-data-jpa')
compile('org.springframework.boot:spring-boot-starter-jdbc')
runtime('mysql:mysql-connector-java')
|
映射关系
一对一
据说这是性能最好的方式, 但是有一点让人不舒服, A的id是名存实亡的, 数据库都没有这个字段, 实际上就是B的id, 但是对象又一定要保留这个id, 不然约束通不过
也就是说, 创建的时候要设置A的id的值, 但是后面却用不到这个值
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
|
@Entity
@Data
public class A {
@Id
private String id;
private String name;
@OneToOne(fetch = FetchType.LAZY)
@MapsId
private B b;
}
@Data
@Entity
public class B implements Serializable {
@Id
private String id;
private String name;
}
|
一对多
- 一方的配置是当前类的id,多方则按基本ER的规则来,注解中配置的是外键的名字, 所以当前类中的属性,外键名是不能重复的
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
|
// 一方
public class TestOne{
@Id
private String testOneId;
@OneToMany
@JoinColumn(name = "testOneId")//这个名字可以重复,最终会有一个随机码生成
private Set<TestMany> testManySet;
}
// 多方
public class TestMany {
@Id
private String testManyId;
@ManyToOne
@JoinColumn(name = "testOneId")
private TestOne testOneId;
}
|
多对多
Mybatis
Mybatis
Non Relational database
Redis
Spring Data Redis
配置连接信息
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
|
# REDIS (RedisProperties)
# Redis数据库索引(默认为0)
spring.redis.database=0
# Redis服务器地址
spring.redis.host=127.0.0.1
# Redis服务器连接端口
spring.redis.port=6379
# Redis服务器连接密码(默认为空)
spring.redis.password=
# 连接池最大连接数(使用负值表示没有限制)
spring.redis.pool.max-active=8
# 连接池最大阻塞等待时间(使用负值表示没有限制)
spring.redis.pool.max-wait=-1
# 连接池中的最大空闲连接
spring.redis.pool.max-idle=8
# 连接池中的最小空闲连接
spring.redis.pool.min-idle=0
# 连接超时时间(毫秒)0不超时
spring.redis.timeout=0
|
在一个配置类中复制如下代码即可使用 StringRedisTemplate RedisTemplate 的实例
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
|
@Bean
public RedisTemplate<Object,Object> redisTemplate(RedisConnectionFactory factory) {
RedisTemplate<Object,Object> template = new RedisTemplate<>();
Jackson2JsonRedisSerializer jackson2JsonRedisSerializer = new Jackson2JsonRedisSerializer<>(Object.class);
template.setConnectionFactory(factory);
ObjectMapper om = new ObjectMapper();
om.setVisibility(PropertyAccessor.ALL, JsonAutoDetect.Visibility.ANY);
om.enableDefaultTyping(ObjectMapper.DefaultTyping.NON_FINAL);
jackson2JsonRedisSerializer.setObjectMapper(om);
// 值序列化采用 jackson2JsonRedisSerializer
template.setValueSerializer(jackson2JsonRedisSerializer);
// 键序列化采用 StringRedisSerializer
template.setKeySerializer(new StringRedisSerializer());
template.afterPropertiesSet();
return template;
}
@Bean
StringRedisTemplate template(RedisConnectionFactory connectionFactory) {
return new StringRedisTemplate(connectionFactory);
}
|
两个对象的简单使用
1
2
3
4
5
6
7
|
stringRedisTemplate.opsForValue().set("aaa", "hello");
String result = stringRedisTemplate.opsForValue().get("aaa");
//获取所有
Set<String> keysList = stringRedisTemplate.keys("*");
for(String temp :keysList){
log.info(temp);
}
|
- 以上配置的template都是只是建立在最简单的键值对上,String-String,所以对象使用的是json来存储
- 但是使用的时候如同使用MySQL一样,是ORM框架自动处理数据的转换
消息订阅和发布
参考: Spring Boot使用Redis进行消息的发布订阅
Neo4j
注意版本不同配置方式不同,可通过自动装配类找到配置类进行分辨