我有两个数据库,MySQL 和 Clickhouse。
我为两个数据库创建了两个单独的配置:
对于 MySQL(这是主要的):
@EnableJpaRepositories(
entityManagerFactoryRef = "mysqlEM",
basePackages = {"com.myproject.repository.mysqlrepos"})
@Configuration(proxyBeanMethods = false)
public class MySQLDatasourceConfiguration {
@Bean
@Primary
@ConfigurationProperties("spring.datasource.mysql")
public DataSourceProperties mysqlDbProperties() {
return new DataSourceProperties();
}
@Bean
@Primary
@ConfigurationProperties("spring.datasource.mysql.hikari")
public HikariDataSource mysqlDataSource(
DataSourceProperties mysqlDbProperties) {
return mysqlDbProperties
.initializeDataSourceBuilder()
.type(HikariDataSource.class)
.build();
}
@Bean(name = "mysqlEM")
@Primary
public LocalContainerEntityManagerFactoryBean mysqlEntityManagerFactory(
EntityManagerFactoryBuilder builder, DataSource mysqlDataSource) {
HashMap<String, Object> properties = new HashMap<>();
return builder.dataSource(mysqlDataSource)
.properties(properties)
.packages("com.myproject.entity.mysqlentities")
.persistenceUnit("mysql")
.build();
}
}
对于Clickhouse:
@EnableJpaRepositories(
entityManagerFactoryRef = "clickhouseEM",
basePackages = {"com.myproject.repository.clickhouserepos"})
@Configuration(proxyBeanMethods = false)
public class ClickhouseDatasourceConfiguration {
@Bean
@ConfigurationProperties("spring.datasource.clickhouse")
public DataSourceProperties clickhouseDbProperties() {
return new DataSourceProperties();
}
@Bean
@ConfigurationProperties("spring.datasource.clickhouse.hikari")
public HikariDataSource clickhouseDataSource(
DataSourceProperties clickhouseDbProperties) {
return clickhouseDbProperties
.initializeDataSourceBuilder()
.type(HikariDataSource.class)
.build();
}
@Bean(name = "clickhouseEM")
public LocalContainerEntityManagerFactoryBean clickhouseEntityManagerFactory(
EntityManagerFactoryBuilder builder, DataSource clickhouseDataSource) {
HashMap<String, Object> properties = new HashMap<>();
return builder.dataSource(clickhouseDataSource)
.properties(properties)
.packages("com.myproject.entity.clickhouseentities")
.persistenceUnit("clickhouse")
.build();
}
}
所有 MySQL 存储库都扩展了
JPARepository
。
对于 Clickhouse,我创建了一个自定义存储库,使用一种方法针对 Clickhouse 运行本机“选择”查询。
这是存储库界面:
@Repository
public interface MyClickhouseRepository {
List<MyClickhouseEntity> findSomeoneInClickhouse(String name);
}
这是它的实现:
@Repository
public class MyClickhouseRepositoryImpl implements MyClickhouseRepository {
@Autowired
@Qualifier("clickhouseEM") EntityManager em;
@Override
public List<MyClickhouseEntity> findSomeoneInClickhouse(String name) {
Query query = em.createNativeQuery("select * from myschema.mytable final where name = :name", MyClickhouseEntity.class);
query.setParameter("name", name);
List<MyClickhouseEntity> res = query.getResultList();
return res;
}
}
应用程序启动成功,但是当我调用
findSomeoneInClickhouse(String)
的 MyClickhouseRepositoryImpl
方法时,它会抛出错误:
Caused by: java.sql.SQLSyntaxErrorException: Unknown database 'myschema'
,但是该数据库存在于 Clickhouse 中。
如果我运行具有 Clickhouse 特定关键字的查询,它会抛出错误:
You have an error in your SQL syntax; check the manual that corresponds to your MySQL server version for the right syntax to use
这两个错误都表明我的应用程序仅查询 MySQL 并且不使用 Clickhouse,即使我在存储库中使用
clickhouseEM
实体管理器。
如果我从 MySQL 配置中删除
@Primary
注释,并将它们添加到 Clickhouse 配置中,事情就会相反 - 我的应用程序仅查询 Clickhouse,并且不使用 MySQL。
有什么想法我可能会错过吗?
看起来数据源方法中注入的
DataSourceProperties
就是@Primary
。使用 DataSourceProperties
注释确保在数据源方法中注入的 @Qualifier
对于每个数据源都是正确的:
@Bean
@Primary
@ConfigurationProperties("spring.datasource.mysql.hikari")
public HikariDataSource mysqlDataSource(
@Qualifier("mysqlDbProperties") DataSourceProperties mysqlDbProperties) {
return mysqlDbProperties
.initializeDataSourceBuilder()
.type(HikariDataSource.class)
.build();
}
@Bean
@ConfigurationProperties("spring.datasource.clickhouse.hikari")
public HikariDataSource clickhouseDataSource(
@Qualifier("clickhouseDbProperties") DataSourceProperties clickhouseDbProperties) {
return clickhouseDbProperties
.initializeDataSourceBuilder()
.type(HikariDataSource.class)
.build();
}
我还认为数据源方法上的
@ConfigurationProperties
注释是不需要的,您可以将其删除。