Spring Boot JPA 多数据源错误

问题描述 投票:0回答:3

我想将我的 Spring Boot 应用程序连接到 2 个数据库。所以根据教程我创建了 2 个配置类。

配置类别 1

@Configuration
@EnableTransactionManagement
@PropertySource({ "classpath:database-configs.properties" })
@EnableJpaRepositories(
        basePackages = {"com.dialog.pod.ideabiz_admin.data_access_objects"},
        entityManagerFactoryRef = "adminEntityManagerFactory",
        transactionManagerRef = "adminTransactionManager")
public class IdeabizAdminConfig {


    @Autowired
    private Environment env;


    @Bean
    PlatformTransactionManager adminTransactionManager() {
        return new JpaTransactionManager(adminEntityManagerFactory().getObject());
    }

    @Bean
    LocalContainerEntityManagerFactoryBean adminEntityManagerFactory() {

        HibernateJpaVendorAdapter jpaVendorAdapter = new HibernateJpaVendorAdapter();
       // jpaVendorAdapter.setGenerateDdl(true);

        LocalContainerEntityManagerFactoryBean factoryBean = new LocalContainerEntityManagerFactoryBean();

        factoryBean.setDataSource(adminDataSource());
        factoryBean.setJpaVendorAdapter(jpaVendorAdapter);
        factoryBean.setPackagesToScan("com.dialog.pod.ideabiz_admin.models");
        factoryBean.setJpaPropertyMap(jpaProperties());
        factoryBean.setPersistenceUnitName("adminDataSource");
        return factoryBean;
    }

    @Bean
    DataSource adminDataSource() {

        DriverManagerDataSource dataSource = new DriverManagerDataSource();
        dataSource.setDriverClassName(env.getProperty("admin.jdbc.driverClassName"));
        dataSource.setUrl(env.getProperty("admin.jdbc.url"));
        dataSource.setUsername(env.getProperty("admin.jdbc.username"));
        dataSource.setPassword(env.getProperty("admin.jdbc.password"));

        return dataSource;
    }


    private Map<String, Object> jpaProperties() {
        Map<String, Object> props = new HashMap<>();
        props.put("hibernate.implicit_naming_strategy","org.hibernate.boot.model.naming.ImplicitNamingStrategyJpaCompliantImpl");
        props.put("hibernate.physical_naming_strategy","com.dialog.pod.PhysicalNamingStrategyImpl");
        return props;
    }


}

配置类别 2

@Configuration
@EnableTransactionManagement
@PropertySource({ "classpath:database-configs.properties" })
@EnableJpaRepositories(
        basePackages = {"com.dialog.pod.ideabiz_log_summary.data_access_objects"},
        entityManagerFactoryRef = "sumLogEntityManagerFactory",
        transactionManagerRef = "sumLogTransactionManager")
public class IdeabizLogSummaryConfig {


    @Autowired
    private Environment env;


    @Bean
    PlatformTransactionManager sumLogTransactionManager() {
        return new JpaTransactionManager(sumLogEntityManagerFactory().getObject());
    }



    @Bean
    LocalContainerEntityManagerFactoryBean sumLogEntityManagerFactory() {


        HibernateJpaVendorAdapter jpaVendorAdapter = new HibernateJpaVendorAdapter();
       // jpaVendorAdapter.setGenerateDdl(true);

        LocalContainerEntityManagerFactoryBean factoryBean = new LocalContainerEntityManagerFactoryBean();

        factoryBean.setDataSource(adminDataSource());
        factoryBean.setJpaVendorAdapter(jpaVendorAdapter);
        factoryBean.setPackagesToScan("com.dialog.pod.ideabiz_log_summary.models");
        factoryBean.setJpaPropertyMap(jpaProperties());
        factoryBean.setPersistenceUnitName("sumLogDataSource");
        return factoryBean;
    }



    @Bean
    DataSource adminDataSource() {

        DriverManagerDataSource dataSource = new DriverManagerDataSource();
        dataSource.setDriverClassName(env.getProperty("sumlog.jdbc.driverClassName"));
        dataSource.setUrl(env.getProperty("sumlog.jdbc.url"));
        dataSource.setUsername(env.getProperty("sumlog.jdbc.username"));
        dataSource.setPassword(env.getProperty("sumlog.jdbc.password"));

        return dataSource;
    }

    private Map<String, Object> jpaProperties() {
        Map<String, Object> props = new HashMap<>();
        props.put("hibernate.implicit_naming_strategy","org.hibernate.boot.model.naming.ImplicitNamingStrategyJpaCompliantImpl");
        props.put("hibernate.physical_naming_strategy","com.dialog.pod.PhysicalNamingStrategyImpl");
        return props;
    }


}

应用类

@SpringBootApplication
@EnableAutoConfiguration (exclude = {  DataSourceAutoConfiguration.class })
@Configuration
@ComponentScan
public class PodApiApplication {

    public static void main(String[] args) {
        SpringApplication.run(PodApiApplication.class, args);
    }

    @Bean
    public WebMvcConfigurer corsConfigurer() {
        return new WebMvcConfigurerAdapter() {
            @Override
            public void addCorsMappings(CorsRegistry registry) {
                registry.addMapping("/").allowedOrigins("*");
            }
        };
    }




}

当我尝试运行该应用程序时,出现以下错误。

***************************
APPLICATION FAILED TO START
***************************

Description:

Method requestMappingHandlerMapping in org.springframework.boot.autoconfigure.web.WebMvcAutoConfiguration$EnableWebMvcConfiguration required a single bean, but 2 were found:
    - adminEntityManagerFactory: defined by method 'adminEntityManagerFactory' in class path resource [com/dialog/pod/ideabiz_admin/IdeabizAdminConfig.class]
    - sumLogEntityManagerFactory: defined by method 'sumLogEntityManagerFactory' in class path resource [com/dialog/pod/ideabiz_log_summary/IdeabizLogSummaryConfig.class]


Action:

Consider marking one of the beans as @Primary, updating the consumer to accept multiple beans, or using @Qualifier to identify the bean that should be consumed


Process finished with exit code 1

我将 @Primary 放入第一个配置类(根据另一个教程)。当我在第一个配置类中执行该数据源时,该数据源有效。问题是当我执行此操作时,第一个数据源也应用于所有 jparepositories。

我是 Spring Boot 新手。我已经尝试解决这个问题超过 5 个小时了:(。提前感谢您提供的任何帮助。

完整日志

2017-01-27 00:52:39.713  INFO 6704 --- [           main] com.dialog.pod.PodApiApplication         : Starting PodApiApplication on DESKTOP-4B89ITN with PID 6704 (started by y2ksh in H:\Spring MVC Workspace\platform-overview-dashboard\PODApi)
2017-01-27 00:52:39.718  INFO 6704 --- [           main] com.dialog.pod.PodApiApplication         : No active profile set, falling back to default profiles: default
2017-01-27 00:52:39.938  INFO 6704 --- [           main] ationConfigEmbeddedWebApplicationContext : Refreshing org.springframework.boot.context.embedded.AnnotationConfigEmbeddedWebApplicationContext@6e171cd7: startup date [Fri Jan 27 00:52:39 IST 2017]; root of context hierarchy
2017-01-27 00:52:41.712  INFO 6704 --- [           main] o.s.b.f.s.DefaultListableBeanFactory     : Overriding bean definition for bean 'adminDataSource' with a different definition: replacing [Root bean: class [null]; scope=; abstract=false; lazyInit=false; autowireMode=3; dependencyCheck=0; autowireCandidate=true; primary=false; factoryBeanName=ideabizAdminConfig; factoryMethodName=adminDataSource; initMethodName=null; destroyMethodName=(inferred); defined in class path resource [com/dialog/pod/ideabiz_admin/IdeabizAdminConfig.class]] with [Root bean: class [null]; scope=; abstract=false; lazyInit=false; autowireMode=3; dependencyCheck=0; autowireCandidate=true; primary=false; factoryBeanName=ideabizLogSummaryConfig; factoryMethodName=adminDataSource; initMethodName=null; destroyMethodName=(inferred); defined in class path resource [com/dialog/pod/ideabiz_log_summary/IdeabizLogSummaryConfig.class]]
2017-01-27 00:52:42.804  INFO 6704 --- [           main] trationDelegate$BeanPostProcessorChecker : Bean 'org.springframework.transaction.annotation.ProxyTransactionManagementConfiguration' of type [class org.springframework.transaction.annotation.ProxyTransactionManagementConfiguration$$EnhancerBySpringCGLIB$$3cc0fc3] is not eligible for getting processed by all BeanPostProcessors (for example: not eligible for auto-proxying)
2017-01-27 00:52:43.594  INFO 6704 --- [           main] s.b.c.e.t.TomcatEmbeddedServletContainer : Tomcat initialized with port(s): 8081 (http)
2017-01-27 00:52:43.609  INFO 6704 --- [           main] o.apache.catalina.core.StandardService   : Starting service Tomcat
2017-01-27 00:52:43.609  INFO 6704 --- [           main] org.apache.catalina.core.StandardEngine  : Starting Servlet Engine: Apache Tomcat/8.5.6
2017-01-27 00:52:43.810  INFO 6704 --- [ost-startStop-1] o.a.c.c.C.[Tomcat].[localhost].[/]       : Initializing Spring embedded WebApplicationContext
2017-01-27 00:52:43.810  INFO 6704 --- [ost-startStop-1] o.s.web.context.ContextLoader            : Root WebApplicationContext: initialization completed in 3891 ms
2017-01-27 00:52:44.247  INFO 6704 --- [ost-startStop-1] o.s.b.w.servlet.ServletRegistrationBean  : Mapping servlet: 'dispatcherServlet' to [/]
2017-01-27 00:52:44.253  INFO 6704 --- [ost-startStop-1] o.s.b.w.servlet.FilterRegistrationBean   : Mapping filter: 'metricFilter' to: [/*]
2017-01-27 00:52:44.254  INFO 6704 --- [ost-startStop-1] o.s.b.w.servlet.FilterRegistrationBean   : Mapping filter: 'characterEncodingFilter' to: [/*]
2017-01-27 00:52:44.254  INFO 6704 --- [ost-startStop-1] o.s.b.w.servlet.FilterRegistrationBean   : Mapping filter: 'hiddenHttpMethodFilter' to: [/*]
2017-01-27 00:52:44.254  INFO 6704 --- [ost-startStop-1] o.s.b.w.servlet.FilterRegistrationBean   : Mapping filter: 'httpPutFormContentFilter' to: [/*]
2017-01-27 00:52:44.254  INFO 6704 --- [ost-startStop-1] o.s.b.w.servlet.FilterRegistrationBean   : Mapping filter: 'requestContextFilter' to: [/*]
2017-01-27 00:52:44.255  INFO 6704 --- [ost-startStop-1] o.s.b.w.servlet.FilterRegistrationBean   : Mapping filter: 'webRequestLoggingFilter' to: [/*]
2017-01-27 00:52:44.255  INFO 6704 --- [ost-startStop-1] o.s.b.w.servlet.FilterRegistrationBean   : Mapping filter: 'applicationContextIdFilter' to: [/*]
2017-01-27 00:52:44.367  INFO 6704 --- [           main] o.s.j.d.DriverManagerDataSource          : Loaded JDBC driver: com.mysql.jdbc.Driver
2017-01-27 00:52:44.403  INFO 6704 --- [           main] j.LocalContainerEntityManagerFactoryBean : Building JPA container EntityManagerFactory for persistence unit 'adminDataSource'
2017-01-27 00:52:44.435  INFO 6704 --- [           main] o.hibernate.jpa.internal.util.LogHelper  : HHH000204: Processing PersistenceUnitInfo [
    name: adminDataSource
    ...]
2017-01-27 00:52:44.634  INFO 6704 --- [           main] org.hibernate.Version                    : HHH000412: Hibernate Core {5.0.11.Final}
2017-01-27 00:52:44.636  INFO 6704 --- [           main] org.hibernate.cfg.Environment            : HHH000206: hibernate.properties not found
2017-01-27 00:52:44.641  INFO 6704 --- [           main] org.hibernate.cfg.Environment            : HHH000021: Bytecode provider name : javassist
2017-01-27 00:52:44.725  INFO 6704 --- [           main] o.hibernate.annotations.common.Version   : HCANN000001: Hibernate Commons Annotations {5.0.1.Final}
2017-01-27 00:52:45.302  INFO 6704 --- [           main] org.hibernate.dialect.Dialect            : HHH000400: Using dialect: org.hibernate.dialect.MySQL5Dialect
2017-01-27 00:52:46.178  INFO 6704 --- [           main] j.LocalContainerEntityManagerFactoryBean : Initialized JPA EntityManagerFactory for persistence unit 'adminDataSource'
2017-01-27 00:52:46.189  INFO 6704 --- [           main] j.LocalContainerEntityManagerFactoryBean : Building JPA container EntityManagerFactory for persistence unit 'sumLogDataSource'
2017-01-27 00:52:46.190  INFO 6704 --- [           main] o.hibernate.jpa.internal.util.LogHelper  : HHH000204: Processing PersistenceUnitInfo [
    name: sumLogDataSource
    ...]
2017-01-27 00:52:46.228  INFO 6704 --- [           main] org.hibernate.dialect.Dialect            : HHH000400: Using dialect: org.hibernate.dialect.MySQL5Dialect
2017-01-27 00:52:46.291  INFO 6704 --- [           main] j.LocalContainerEntityManagerFactoryBean : Initialized JPA EntityManagerFactory for persistence unit 'sumLogDataSource'
2017-01-27 00:52:46.695  INFO 6704 --- [           main] o.h.h.i.QueryTranslatorFactoryInitiator  : HHH000397: Using ASTQueryTranslatorFactory
2017-01-27 00:52:46.947  INFO 6704 --- [           main] o.h.h.i.QueryTranslatorFactoryInitiator  : HHH000397: Using ASTQueryTranslatorFactory
2017-01-27 00:52:47.496  INFO 6704 --- [           main] s.w.s.m.m.a.RequestMappingHandlerAdapter : Looking for @ControllerAdvice: org.springframework.boot.context.embedded.AnnotationConfigEmbeddedWebApplicationContext@6e171cd7: startup date [Fri Jan 27 00:52:39 IST 2017]; root of context hierarchy
2017-01-27 00:52:47.560  WARN 6704 --- [           main] ationConfigEmbeddedWebApplicationContext : Exception encountered during context initialization - cancelling refresh attempt: org.springframework.beans.factory.BeanCreationException: Error creating bean with name 'requestMappingHandlerMapping' defined in class path resource [org/springframework/boot/autoconfigure/web/WebMvcAutoConfiguration$EnableWebMvcConfiguration.class]: Bean instantiation via factory method failed; nested exception is org.springframework.beans.BeanInstantiationException: Failed to instantiate [org.springframework.web.servlet.mvc.method.annotation.RequestMappingHandlerMapping]: Factory method 'requestMappingHandlerMapping' threw exception; nested exception is org.springframework.beans.factory.BeanCreationException: Error creating bean with name 'openEntityManagerInViewInterceptor' defined in class path resource [org/springframework/boot/autoconfigure/orm/jpa/JpaBaseConfiguration$JpaWebConfiguration$JpaWebMvcConfiguration.class]: Initialization of bean failed; nested exception is org.springframework.beans.factory.NoUniqueBeanDefinitionException: No qualifying bean of type 'javax.persistence.EntityManagerFactory' available: expected single matching bean but found 2: adminEntityManagerFactory,sumLogEntityManagerFactory
2017-01-27 00:52:47.562  INFO 6704 --- [           main] j.LocalContainerEntityManagerFactoryBean : Closing JPA EntityManagerFactory for persistence unit 'sumLogDataSource'
2017-01-27 00:52:47.563  INFO 6704 --- [           main] j.LocalContainerEntityManagerFactoryBean : Closing JPA EntityManagerFactory for persistence unit 'adminDataSource'
2017-01-27 00:52:47.566  INFO 6704 --- [           main] o.apache.catalina.core.StandardService   : Stopping service Tomcat
2017-01-27 00:52:47.586  INFO 6704 --- [           main] utoConfigurationReportLoggingInitializer : 

Error starting ApplicationContext. To display the auto-configuration report re-run your application with 'debug' enabled.
2017-01-27 00:52:47.592 ERROR 6704 --- [           main] o.s.b.d.LoggingFailureAnalysisReporter   : 

***************************
APPLICATION FAILED TO START
***************************

Description:

Method requestMappingHandlerMapping in org.springframework.boot.autoconfigure.web.WebMvcAutoConfiguration$EnableWebMvcConfiguration required a single bean, but 2 were found:
    - adminEntityManagerFactory: defined by method 'adminEntityManagerFactory' in class path resource [com/dialog/pod/ideabiz_admin/IdeabizAdminConfig.class]
    - sumLogEntityManagerFactory: defined by method 'sumLogEntityManagerFactory' in class path resource [com/dialog/pod/ideabiz_log_summary/IdeabizLogSummaryConfig.class]


Action:

Consider marking one of the beans as @Primary, updating the consumer to accept multiple beans, or using @Qualifier to identify the bean that should be consumed


Process finished with exit code 1
spring hibernate jpa spring-boot spring-data
3个回答
6
投票

将其中一颗豆标记为主要豆

    @Primary
    @Bean
    public EntityManagerFactory entityManagerFactory() {
}

4
投票

您的 Spring Boot 应用程序通过

WebMvcAutoConfiguration
隐式激活 Spring Web Mvc,这是通过在类路径中包含
Servlet.class
等内容来触发的。这个
WebMvcAutoConfiguration
需要一个
EntityManagerFactory
类型的 bean。但是,您已经注册了两个这样的 Bean
adminEntityManagerFactory
sumLogEntityManagerFactory
。因此,您必须通过相应
@Primary
方法之上的
@Bean
告诉 Spring Web Mvc 哪一个是您的首选。或者,如果您不需要 Web Mvc 自动配置,请通过
@EnableAutoConfiguration(exclude={WebMvcAutoConfiguration})
将其关闭并手动配置 Web Mvc。


1
投票

事实证明我对两个数据源 bean 使用了相同的方法名称。这就是为什么所有 jparepos 只使用一个数据源的原因。感谢@Javatar81 解释 bean 命名是如何工作的

© www.soinside.com 2019 - 2024. All rights reserved.