本文介绍了Spring Data JPA - 多个EnableJpaRepositories的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我的应用程序有多个数据源,所以我已经根据这个。



但是,当运行spring启动应用程序时出现错误

从这个帮助我我需要在我的JPA存储库中指定entityManagerFactoryRef。



但是我有很多存储库类,其中一些使用Entitymanager'A',其中一些使用' B'。我当前的Spring启动应用程序类是这样的

  @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。运行(CavionApplication.class,args);
}
@Bean
public CommandLineRunner commandLineRunner(ApplicationContext ctx){
return args - > {

System.out.println(让我们来看看Spring Boot提供的bean:);

String [] beanNames = ctx.getBeanDefinitionNames();
Arrays.sort(beanNames);
for(String beanName:beanNames){
System.out.println(beanName);
}

};
}}

我在Spring Boot类中给出了EnableJpaRepositories,配置多个EnableJpaRepositories,以便我可以配置多个entityManagerFactory?



请建议设置多个数据源的最佳方式。

与什么 Repository 注释中定义它。假设我们有两个实体: Servers 实体和 Domains 实体,并且每个实体都有自己的Repo,然后每个Repository具有自己的JpaDataSource配置。



1。根据它们相关的数据源对所有存储库进行分组。例如
$ b 域实体的存储库(包: org.springdemo .multiple.datasources.repository.domains ):

  package org.springdemo.multiple.datasources。 repository.domains; 

导入org.springdemo.multiple.datasources.domain.domains.Domains;
import org.springframework.data.jpa.repository.JpaRepository;

公共接口DomainsRepository扩展了JpaRepository< Domains,Long> {
}

服务器实体(包: org.springdemo.multiple.datasources.repository.servers )

  package org.springdemo.multiple.datasources.repository.servers; 

导入org.springdemo.multiple.datasources.domain.servers.Servers;
import org.springframework.data.jpa.repository.JpaRepository;

公共接口ServersRepository扩展了JpaRepository< Servers,Long> {
}

2。对于每个JPA Data Soruce,您需要定义一个配置,在本例中,我将展示如何配置两个不同的DataSources

域 Jpa配置:数据源与存储库之间的关系在 basePackages 值中定义,这就是为什么将存储库分组到取决于每个回购将使用的实体管理器的不同包。

  @Configuration 
@EnableJpaRepositories(
entityManagerFactoryRef =domainsEntityManager,
transactionManagerRef = domainsTransactionManager,
basePackages = {org.springdemo.multiple.datasources.repository.domains}

public class DomainsConfig {

服务器数据源配置:您可以看到basePackages的值包含 Servers Repository以及 entityManagerFactoryRef 和 transactionManagerRef 的值在


$ @ $ $ b $ @ $ $ $ $ @ $ $ $ $ $ entityManagerFactoryRef =serversEntityManager ,
transactionManagerRef =serversTransactionManager,
basePackages = {org.springdemo.multiple.datasources.repository.servers}

public cl ServersConfig {

3。将一个数据源设置为主要



为了避免错误消息: org.springframework.boot.autoconigure中构造函数的参数0 .orm.jpa.HibernateJpaAutoConfiguration需要一个bean,但是找到了2个:只需将其中一个数据源设置为@Primary,在本例中我选择 Servers
$ p $ @Bean(serversDataSourceProperties)
@Primary
@ConfigurationProperties (app.datasource.servers)
public DataSourceProperties serversDataSourceProperties(){
return new DataSourceProperties();



$ b @Bean(serversDataSource)
@Primary
@ConfigurationProperties(app.datasource.servers)
public DataSource serversDataSource(@Qualifier(serversDataSourceProperties)DataSourceProperties serversDataSourceProperties){
returns serversDataSourceProperties()。initializeDataSourceBuilder()。build();

$ / code>

如果您需要更多信息,请参阅每个配置的完整示例: p>

服务器 JPA配置

  @Configuration 
@EnableJpaRepositories(
entityManagerFactoryRef =serversEntityManager,
transactionManagerRef =serversTransactionManager,
basePackages = {org.springdemo.multiple.datasources.repository。服务器}

公共类ServersConfig {

@Bean(name =serversEntityManager)
public LocalContainerEntityManagerFactoryBean getServersEntityManager(EntityManagerFactoryBuilder构建器,
@Qualifier (serversDataSource)DataSource serversDataSource){


返回生成器
.dataSource(serversDataSource)
.packages(org.springdemo.multiple.datasources.domain。服务器 )
.persistenceUnit(servers)
.properties(additionalJpaProperties())
.build();

}

地图< 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);

返回地图;


$ b @Bean(serversDataSourceProperties)
@Primary
@ConfigurationProperties(app.datasource.servers)
public DataSourceProperties serversDataSourceProperties(){
返回新的DataSourceProperties();



$ b @Bean(serversDataSource)
@Primary
@ConfigurationProperties(app.datasource.servers)
public DataSource serversDataSource(@Qualifier(serversDataSourceProperties)DataSourceProperties serversDataSourceProperties){
returns serversDataSourceProperties()。initializeDataSourceBuilder()。build();

$ b $Bean(name =serversTransactionManager)
public JpaTransactionManager transactionManager(@Qualifier(serversEntityManager)EntityManagerFactory serversEntityManager){
JpaTransactionManager transactionManager = new JpaTransactionManager ();
transactionManager.setEntityManagerFactory(serversEntityManager);

返回transactionManager;




$ b $ @ $ Configuration
@EnableJpaRepositories(
entityManagerFactoryRef =domainsEntityManager,
transactionManagerRef =domainsTransactionManager,
basePackages = {org.springdemo.multiple.datasources.repository.domains}

public class DomainsConfig {

@Bean(name =domainsEntityManager)
public LocalContainerEntityManagerFactoryBean getdomainsEntityManager(EntityManagerFactoryBuilder构建器
,@ Qualifier(domainsDataSource)DataSource domainsDataSource){

返回构建器
。 dataSource(domainsDataSource)
.packages(org.springdemo.multiple.datasources.domain.domains)
.persistenceUnit(domains)
.properties(additionalJpaProperties())
.build();

}


地图< 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);

返回地图;


$ b @Bean(domainsDataSourceProperties)
@ConfigurationProperties(app.datasource.domains)
public DataSourceProperties domainsDataSourceProperties(){
返回新的DataSourceProperties();


$ b @Bean(domainsDataSource)
public DataSource domainsDataSource(@Qualifier(domainsDataSourceProperties)DataSourceProperties domainsDataSourceProperties){
返回domainsDataSourceProperties。 initializeDataSourceBuilder()建立();

$ b $Bean(name =domainsTransactionManager)
public JpaTransactionManager transactionManager(@Qualifier(domainsEntityManager)EntityManagerFactory domainsEntityManager){
JpaTransactionManager transactionManager = new JpaTransactionManager ();
transactionManager.setEntityManagerFactory(domainsEntityManager);

返回transactionManager;
}

}

为了将每个数据源I将配置放在 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

如果您需要更多信息,请参阅以下文档:



如何配置两个不同的数据库的示例:


My application has multiple data sources , so i have created two data source configuration classes based on this URL .

But while running the spring boot application am getting error

From this Question on StackOverflow helped me to figure out the issue.i need to specify the entityManagerFactoryRef on my JPA repositories .

But i have many repository classes some of them uses Entitymanager 'A' and some of them uses 'B' . my current spring boot application class is like this

@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);
        }

    };
}}

I have given the EnableJpaRepositories on the spring boot class , so how can i configure multiple EnableJpaRepositories so that i can configure multiple entityManagerFactory ?

Please suggest the best way to setup the multiple data sources .

解决方案

In order to let spring knows what DataSource is related to what Repository you should define it at the @EnableJpaRepositories annotation. Let's assume that we have two entities, the Servers entity and the Domains entity and each one has its own Repo then each Repository has its own JpaDataSource configuration.

1. Group all the repositories based on the Data Source that they are related to. For example

Repository for Domains entities (package: 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> {
}

Repository for Servers entities (package: 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> {
}

2. For each JPA Data Soruce you need to define a configuration, in this example I show how to configure two different DataSources

Domains Jpa Configuration: the relationship between the Data Source and the repository is defined in the basePackages value, that is the reason why is necessary to group the repositories in different packages depending on the entity manager that each repo will use.

@Configuration
@EnableJpaRepositories(
        entityManagerFactoryRef = "domainsEntityManager",
        transactionManagerRef = "domainsTransactionManager",
        basePackages = {"org.springdemo.multiple.datasources.repository.domains"}
        )
public class DomainsConfig {

Servers Data Source Configuration: as you can see the basePackages value has the package name of the Servers Repository , and also the values of entityManagerFactoryRef and transactionManagerRef are different in order to let spring separate each entityManager.

@Configuration
@EnableJpaRepositories(
        entityManagerFactoryRef = "serversEntityManager",
        transactionManagerRef = "serversTransactionManager",
        basePackages = {"org.springdemo.multiple.datasources.repository.servers"}
        )
public class ServersConfig {

3. Set one Datasource as primary

In order to avoid the error message: Parameter 0 of constructor in org.springframework.boot.autoconfigure.orm.jpa.HibernateJpaAutoConfiguration required a single bean, but 2 were found: just set one of the datasource as @Primary, in this example I select the Servers Datasource as 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();
}

If you need more information please see the full example for each configuration:

Servers JPA Configuration

@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;
    }
}

Domains JPA Configuration

@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;
    }

}

In order to separate each datasource I put the configuration in the application.properties file, like this:

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

If you need more information please see the following documentation:

Spring Documentation: howto-two-datasources

A similar example of how configure two different databases: github example

这篇关于Spring Data JPA - 多个EnableJpaRepositories的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持!

08-21 02:41