当前位置: 首页 > 面试题库 >

Spring Data JPA-多个EnableJpaRepositories

羊舌自强
2023-03-14
问题内容

我的应用程序具有多个数据源,因此我基于此URL创建了两个数据源配置类 。

但是在运行spring boot应用程序时出现错误

说明:com.cavion.services.UserDataService中的userDataRepo字段需要找不到名为’entityManagerFactory’的bean。行动:考虑在你的配置中定义一个名为“ entityManagerFactory”的bean。

从StackOverflow上的这个问题中可以帮助我弄清楚问题。我需要在我的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?

请提出设置多个数据源的最佳方法。


问题答案:

为了让spring知道DataSource与之相关的内容,Repository你应该在@EnableJpaRepositories注释中对其进行定义。假设我们有两个实体,Servers实体和Domains实体,并且每个实体都有自己的存储库,那么每个存储库都有自己的JpaDataSource配置。

1.根据与它们相关的数据源将所有存储库分组。例如

Domains实体存储库(包:)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.html" target="_blank">jpa.repository.JpaRepository;

public interface ServersRepository extends JpaRepository<Servers,Long> {
}

2.对于每个JPA Data Soruce,你需要定义一个配置,在此示例中,我演示了如何配置两个不同的DataSources

DomainsJpa配置:basePackages值中定义了数据源与存储库之间的关系,这就是为什么有必要根据每个存储库将使用的实体管理器将存储库分组到不同程序包中的原因。

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

Servers数据源配置:正如你所看到的basePackages值具有的包名Servers库,并且还值entityManagerFactoryReftransactionManagerRef是为了让spring分隔每个EntityManager的不同。

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

3.将一个数据源设置为主数据库

为了避免出现错误消息:Parameter 0 of constructor in org.springframework.boot.autoconfigure.orm.jpa.HibernateJpaAutoConfiguration required a single bean, but 2 were found:只需将数据源之一设置为@Primary,在本示例中,我将Servers数据源选择为主数据库:

@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 JPA配置

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

}

为了分离每个数据源,我将配置放入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


 类似资料:
  • 我只想不使用xml,所以我需要非xml替代这些设置。这是我的POM。

  • 我的项目中的三个模型对象(本文末尾的模型和存储库片段)之间确实存在关系。 当我调用时,它会触发三个select查询: (“sql”) (对我来说)那是相当不寻常的行为。在阅读Hibernate文档后,我认为它应该始终使用连接查询。当类中的更改为时,查询没有区别(使用附加选择进行查询),当更改为时,城市类的查询也一样(使用JOIN进行查询)。 当我使用抑制火灾时,有两种选择: 我的目标是在所有情况下

  • SpringDataJpa中 Specification怎样使用in查询 实体类Menu.java如下 想通过roles属性做in查询,代码如下 错误如下: Parameter value [com.appmtce.pojo.entity.role.Role@20f81e2a] did not match expected type [java.util.Collection (n/a)] 我的S

  • 或者,使用风味,在这种情况下,所有自由变体都将具有相同的符号configs: 在当前的ProductFlayer闭包中有没有一种方法可以做到这一点?是否只能通过重写并基于某种命名方案或其他丑陋的黑客行为为每个应用程序变体手动应用signingConfig来解决这个问题? 我也找到了这个答案,但在最新的构建工具中似乎不起作用;编译时,我得到以下错误:

  • 我目前正在用Laravel构建我的第一个应用程序,我偶然发现了一个问题,即我不知道如何设置模型(用户和组)之间的多对多关系。 我已经创建了一个板,其中存储了所有用户和他们所在的组之间的关系。我的问题是,我不知道如何访问和设置这在Laravel。我不确定我是否必须用户has很多或属性。 我正试图找到一种方法,将用户添加到组中,以便在UserGroups表中创建一个新条目。 我的桌子: 用户 ID 集

  • 我继承了一个项目,它有一些CRUD形式...在创建表单中,我们需要创建一个和关系的条目。所以基本上我得到的是以下这些 我不确定这是否是最好的方法,但似乎有效。 我遇到的问题是,在表单中,这些参与者/评论可以编辑、添加或删除,我不确定如何更新它们。是否可以更新它们,或者删除现有关系数据并重新添加它们是否更好? 我从来没有更新过关系,只是添加了它们,所以我不确定如何开始。 任何帮助都将不胜感激。

  • 我读过很多关于这方面的文章,但也有2012年或更早的文章。 (我只是打算从数据库中读取和插入一些数据。)

  • 我正在使用100个实体(使用JHipster)设置一个新的Spring Boot API,我的问题是:鉴于我有一组存储库层方法,我希望我的所有存储库都能够调用这些方法。 我已经尝试制作所有接口来扩展('RepositoryQuery'是我默认的自定义接口名称后缀),然后使用特定于实体的类。请注意,所有的类扩展了一个泛型实现类,名为。 请注意,给定正则表达式中的“.*”代表我的持久实体集中的任何实体