JPA-DataRedis多数据源切换
这里主要基于 SpringBoot
目前的 spring-boot-starter-data-redis
Redis Repositories 依赖.
日常项目使用当中可能不止有单个 Redis, 有时候需要切换多个 Redis 方便读写数据, 这里目前网上数据比较少所以总结下.
首先就是引入目前组件依赖:
<!-- Redis -->
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-data-redis</artifactId>
</dependency>
引入比较简单, 后续关键就是编写配置项, 这里就是相对比较复杂的阶段, 首先是定义 application.properties 内部配置:
# =====================================
# Redis中心库
# =====================================
spring.data.redis.center.host=192.168.1.110
spring.data.redis.center.port=6379
spring.data.redis.center.password=redis2024
spring.data.redis.center.database=0
# =====================================
# Redis会话库
# =====================================
spring.data.redis.session.host=192.168.1.100
spring.data.redis.session.port=6379
spring.data.redis.session.password=redis2024
spring.data.redis.session.database=1
这两个就是不同库对象和连接, 之后就是加载具体配置备用:
/**
* 数据库多库配置, 这里编写集成数据库相关配置
*/
@Configuration
public class DataSourceConfig {
/**
* 注意:
* 1.必须要利用 @Primary 指定默认数据库主库, 其他配置默认都为从库不需要配置该注解
* 2.@Bean最好手动声明指定全局配置数据源名称,也就是指定 name 配置
* 3.@ConfigurationProperties 就是获取到配置文件当中的 spring.data.redis.center 配置项
* 4.@Qualifier 用来指定声明防止其他注册的 Bean 冲突
*/
@Primary
@Bean(name = "CenterDataSource")
@Qualifier("CenterDataSource")
@ConfigurationProperties(prefix = "spring.data.redis.center")
public RedisProperties centerProperties() {
return new RedisProperties();
}
/**
* 注意:
* 1.从库不需要 @Primary 指定默认数据库主库
*/
@Bean(name = "SessionDataSource")
@Qualifier("SessionDataSource")
@ConfigurationProperties(prefix = "spring.data.redis.session")
public RedisProperties sessionProperties() {
return new RedisProperties();
}
}
最后就是定义两个主要 Repositories 来启用连接和数据工厂配置:
// ------------------------------------------
// CenterDataSourceConfig 配置文件
// ------------------------------------------
/**
* Redis配置
* 1. redisTemplateRef 和 keyValueTemplateRef 必须同时配置才能生效
* 2. EnableRedisRepositories.basePackages 用于扫描 repository 接口文件的路径
* 3. EntityScan.basePackages 用于扫描 entity 实体文件的路径
*/
@Configuration
@EnableTransactionManagement
@EnableRedisRepositories(
basePackages = {"com.meteorcat.devops.database.center.repository"},
redisTemplateRef = "CenterRedisTemplateManager",
keyValueTemplateRef = "CenterKeyValueTemplateManager"
)
@EntityScan(
basePackages = {"com.meteorcat.devops.database.center.entity"})
public class CenterDataSourceConfig {
final RedisProperties properties;
public CenterDataSourceConfig(@Qualifier("CenterDataSource") RedisProperties properties) {
this.properties = properties;
}
@Bean("CenterRedisConnectionFactory")
public RedisConnectionFactory connectionFactory() {
RedisStandaloneConfiguration conf = new RedisStandaloneConfiguration();
conf.setHostName(properties.getHost());
conf.setPort(properties.getPort());
conf.setDatabase(properties.getDatabase());
conf.setPassword(properties.getPassword());
return new LettuceConnectionFactory(conf);
}
@Bean("CenterRedisTemplateManager")
public RedisTemplate<?, ?> CenterRedisTemplateManager(@Qualifier("CenterRedisConnectionFactory") RedisConnectionFactory factory) {
System.out.printf("CenterRedisTemplateManager,%d%n", properties.getDatabase());
RedisTemplate<byte[], byte[]> template = new RedisTemplate<>();
template.setConnectionFactory(factory);
template.afterPropertiesSet();
return template;
}
@Bean("CenterKeyValueTemplateManager")
public KeyValueTemplate CenterKeyValueTemplateManager(@Qualifier("CenterRedisTemplateManager") RedisTemplate<?, ?> template) {
return new KeyValueTemplate(
new RedisKeyValueAdapter(template),
new RedisMappingContext()
);
}
}
// ============================================
/**
* Redis配置
*/
@Configuration
@EnableTransactionManagement
@EnableRedisRepositories(
basePackages = {"com.meteorcat.devops.database.session.repository"},
redisTemplateRef = "SessionRedisTemplateManager",
keyValueTemplateRef = "SessionKeyValueTemplateManager"
)
@EntityScan(
basePackages = {"com.meteorcat.devops.database.session.entity"})
public class SessionDataSourceConfig {
final RedisProperties properties;
public SessionDataSourceConfig(@Qualifier("SessionDataSource") RedisProperties properties) {
this.properties = properties;
}
@Bean("SessionRedisConnectionFactory")
public RedisConnectionFactory connectionFactory() {
RedisStandaloneConfiguration conf = new RedisStandaloneConfiguration();
conf.setHostName(properties.getHost());
conf.setPort(properties.getPort());
conf.setDatabase(properties.getDatabase());
conf.setPassword(properties.getPassword());
return new LettuceConnectionFactory(conf);
}
@Bean("SessionRedisTemplateManager")
public RedisTemplate<?, ?> SessionRedisTemplateManager(@Qualifier("SessionRedisConnectionFactory") RedisConnectionFactory factory) {
System.out.printf("SessionRedisTemplateManager,%d%n", properties.getDatabase());
RedisTemplate<byte[], byte[]> template = new RedisTemplate<>();
template.setConnectionFactory(factory);
template.afterPropertiesSet();
return template;
}
@Bean("SessionKeyValueTemplateManager")
public KeyValueTemplate SessionKeyValueTemplateManager(@Qualifier("SessionRedisTemplateManager") RedisTemplate<?, ?> template) {
return new KeyValueTemplate(
new RedisKeyValueAdapter(template),
new RedisMappingContext()
);
}
}
这里就定义两个数据源并且配置两者扫描目录分别是
com.meteorcat.devops.database.sessioncom.meteorcat.devops.database.center
只需要把对应实体文件放置于此就能切换不同数据源写入, 这里创建两个文件分别放置其中测试下是否会在两个不同 Redis 生成:
/**
* 分别放入文件
* com.meteorcat.devops.database.[session|center].entity.[CenterUser|SessionUser].java
*/
@Data
@RedisHash("mem_user")
public class CenterUser implements Serializable {
@Id
@Indexed
private Long id;
private String nickname;
}
// ============================================
/**
* 同样放入
* com.meteorcat.devops.database.[session|center].repository.[ICenterUserRepository|ISessionUserRepository].java
*/
public interface ICenterUserRepository extends CrudRepository<CenterUser, Long> {
}
测试写入两者实体, 看看是否同步数据到不同数据库即可
注意:
Jpa的实体和数据工厂在项目当中不能存在同名, 这是必须要注意的.