我的应用程序有多个数据源,因此我根据此URL创建了两个数据源配置类。
但是在运行spring boot应用程序时遇到错误
描述: com.cavion.services.UserDataService中的字段userDataRepo需要一个名为' entityManagerFactory'的bean。无法找到。 行动: 考虑定义一个名为' entityManagerFactory'在你的配置中。
通过StackOverflow上的这个Question帮助我找出问题。我需要在我的JPA存储库中指定entityManagerFactoryRef。
但我有很多存储库类,其中一些使用Entitymanager' A'其中一些人使用' B' 。我当前的spring boot应用程序类就像这样
@SpringBootApplication(exclude = { DataSourceAutoConfiguration.class, HibernateJpaAutoConfiguration.class,
DataSourceTransactionManagerAutoConfiguration.class })
@EnableTransactionManagement
@EntityScan("com.info.entity")
@ComponentScan({"com.info.services","com.info.restcontroller"})
@EnableJpaRepositories("com.info.repositories")
public class CavionApplication {
public static void main(String[] args) {
SpringApplication.run(CavionApplication.class, args);
}
@Bean
public CommandLineRunner commandLineRunner(ApplicationContext ctx) {
return args -> {
System.out.println("Let's inspect the beans provided by Spring Boot:");
String[] beanNames = ctx.getBeanDefinitionNames();
Arrays.sort(beanNames);
for (String beanName : beanNames) {
System.out.println(beanName);
}
};
}}
我已经在spring引导类上给出了EnableJpaRepositories,那么如何配置多个EnableJpaRepositories以便我可以配置多个entityManagerFactory?
请建议设置多个数据源的最佳方法。
答案 0 :(得分:24)
为了让spring知道Repository
与@EnableJpaRepositories
相关的内容,您应该在Servers
注释中定义它。让我们假设我们有两个实体,Domains
实体和Domains
实体,每个实体都有自己的Repo,然后每个Repository都有自己的JpaDataSource配置。
<强> 1。根据与之相关的数据源对所有存储库进行分组。例如
org.springdemo.multiple.datasources.repository.domains
个实体的存储库(包:package org.springdemo.multiple.datasources.repository.domains;
import org.springdemo.multiple.datasources.domain.domains.Domains;
import org.springframework.data.jpa.repository.JpaRepository;
public interface DomainsRepository extends JpaRepository<Domains,Long> {
}
):
Servers
org.springdemo.multiple.datasources.repository.servers
个实体的存储库(包:package org.springdemo.multiple.datasources.repository.servers;
import org.springdemo.multiple.datasources.domain.servers.Servers;
import org.springframework.data.jpa.repository.JpaRepository;
public interface ServersRepository extends JpaRepository<Servers,Long> {
}
)
Domains
<强> 2。对于每个JPA Data Soruce,您需要定义配置,在此示例中,我将展示如何配置两个不同的DataSource
basePackages
Jpa配置:数据源与存储库之间的关系在@Configuration
@EnableJpaRepositories(
entityManagerFactoryRef = "domainsEntityManager",
transactionManagerRef = "domainsTransactionManager",
basePackages = {"org.springdemo.multiple.datasources.repository.domains"}
)
public class DomainsConfig {
值中定义,这就是为什么需要根据实体管理器将存储库分组到不同的包中的原因每个回购都会使用。
Servers
Servers
数据源配置:如您所见,basePackages值的包名称为entityManagerFactoryRef
存储库,transactionManagerRef
和@Configuration
@EnableJpaRepositories(
entityManagerFactoryRef = "serversEntityManager",
transactionManagerRef = "serversTransactionManager",
basePackages = {"org.springdemo.multiple.datasources.repository.servers"}
)
public class ServersConfig {
的值也不同为了让spring将每个entityManager分开。
Parameter 0 of constructor in org.springframework.boot.autoconfigure.orm.jpa.HibernateJpaAutoConfiguration required a single bean, but 2 were found:
第3。将一个数据源设置为主要
为了避免错误消息:Servers
只需将其中一个数据源设置为@Primary,在本例中我选择@Bean("serversDataSourceProperties")
@Primary
@ConfigurationProperties("app.datasource.servers")
public DataSourceProperties serversDataSourceProperties(){
return new DataSourceProperties();
}
@Bean("serversDataSource")
@Primary
@ConfigurationProperties("app.datasource.servers")
public DataSource serversDataSource(@Qualifier("serversDataSourceProperties") DataSourceProperties serversDataSourceProperties) {
return serversDataSourceProperties().initializeDataSourceBuilder().build();
}
数据源为主要数据:
Servers
如果您需要更多信息,请参阅每个配置的完整示例:
@Configuration
@EnableJpaRepositories(
entityManagerFactoryRef = "serversEntityManager",
transactionManagerRef = "serversTransactionManager",
basePackages = {"org.springdemo.multiple.datasources.repository.servers"}
)
public class ServersConfig {
@Bean(name = "serversEntityManager")
public LocalContainerEntityManagerFactoryBean getServersEntityManager(EntityManagerFactoryBuilder builder,
@Qualifier("serversDataSource") DataSource serversDataSource){
return builder
.dataSource(serversDataSource)
.packages("org.springdemo.multiple.datasources.domain.servers")
.persistenceUnit("servers")
.properties(additionalJpaProperties())
.build();
}
Map<String,?> additionalJpaProperties(){
Map<String,String> map = new HashMap<>();
map.put("hibernate.hbm2ddl.auto", "create");
map.put("hibernate.dialect", "org.hibernate.dialect.MySQLDialect");
map.put("hibernate.show_sql", "true");
return map;
}
@Bean("serversDataSourceProperties")
@Primary
@ConfigurationProperties("app.datasource.servers")
public DataSourceProperties serversDataSourceProperties(){
return new DataSourceProperties();
}
@Bean("serversDataSource")
@Primary
@ConfigurationProperties("app.datasource.servers")
public DataSource serversDataSource(@Qualifier("serversDataSourceProperties") DataSourceProperties serversDataSourceProperties) {
return serversDataSourceProperties().initializeDataSourceBuilder().build();
}
@Bean(name = "serversTransactionManager")
public JpaTransactionManager transactionManager(@Qualifier("serversEntityManager") EntityManagerFactory serversEntityManager){
JpaTransactionManager transactionManager = new JpaTransactionManager();
transactionManager.setEntityManagerFactory(serversEntityManager);
return transactionManager;
}
}
JPA配置
Domains
@Configuration
@EnableJpaRepositories(
entityManagerFactoryRef = "domainsEntityManager",
transactionManagerRef = "domainsTransactionManager",
basePackages = {"org.springdemo.multiple.datasources.repository.domains"}
)
public class DomainsConfig {
@Bean(name = "domainsEntityManager")
public LocalContainerEntityManagerFactoryBean getdomainsEntityManager(EntityManagerFactoryBuilder builder
,@Qualifier("domainsDataSource") DataSource domainsDataSource){
return builder
.dataSource(domainsDataSource)
.packages("org.springdemo.multiple.datasources.domain.domains")
.persistenceUnit("domains")
.properties(additionalJpaProperties())
.build();
}
Map<String,?> additionalJpaProperties(){
Map<String,String> map = new HashMap<>();
map.put("hibernate.hbm2ddl.auto", "create");
map.put("hibernate.dialect", "org.hibernate.dialect.H2Dialect");
map.put("hibernate.show_sql", "true");
return map;
}
@Bean("domainsDataSourceProperties")
@ConfigurationProperties("app.datasource.domains")
public DataSourceProperties domainsDataSourceProperties(){
return new DataSourceProperties();
}
@Bean("domainsDataSource")
public DataSource domainsDataSource(@Qualifier("domainsDataSourceProperties") DataSourceProperties domainsDataSourceProperties) {
return domainsDataSourceProperties.initializeDataSourceBuilder().build();
}
@Bean(name = "domainsTransactionManager")
public JpaTransactionManager transactionManager(@Qualifier("domainsEntityManager") EntityManagerFactory domainsEntityManager){
JpaTransactionManager transactionManager = new JpaTransactionManager();
transactionManager.setEntityManagerFactory(domainsEntityManager);
return transactionManager;
}
}
JPA配置
application.properties
为了分隔每个数据源,我将配置放在app.datasource.domains.url=jdbc:h2:mem:~/test
app.datasource.domains.driver-class-name=org.h2.Driver
app.datasource.servers.driver-class-name=com.mysql.jdbc.Driver
app.datasource.servers.url=jdbc:mysql://localhost:3306/v?autoReconnect=true&useSSL=false
app.datasource.servers.username=myuser
app.datasource.servers.password=mypass
文件中,如下所示:
ModifyEvent
如果您需要更多信息,请参阅以下文档:
Spring Documentation: howto-two-datasources
如何配置两个不同数据库的类似示例:github example
答案 1 :(得分:2)
@Daniel C.提供的答案是正确的。从我身边进行小的校正/观察。
答案 2 :(得分:0)
我刚刚在github中为mysql添加了一个模块感知的多数据库感知库。需要添加一些应用程序属性才能完成。
文档和其他详细信息可以在以下位置找到:-
https://github.com/yatharthamishra0419/spring-boot-data-multimodule-mysql