在 Spring JPA 中连接到两个不同的数据库失败

Posted

技术标签:

【中文标题】在 Spring JPA 中连接到两个不同的数据库失败【英文标题】:Connection to two different databases in Spring JPA fails 【发布时间】:2015-11-12 20:44:47 【问题描述】:

我试图在我的应用程序中使用 2 个不同的数据源/数据库,但到目前为止我无法连接到它们。

FirstDb 配置文件

@Configuration
@EnableTransactionManagement
@EnableJpaRepositories(basePackages = "xx.xx.xx.crud.repository.running", entityManagerFactoryRef = "dummyTestEntityManagerFactory", transactionManagerRef = "transactionManagerOne")
@PropertySource("classpath:application.properties")
public class dummyTestDbConfig 

    @Value("$spring.datasourcedummyTestraid.driver-class-name")
    String driverClassName = "";
    @Value("$spring.datasourcedummyTestraid.url")
    String url = "";
    @Value("$spring.datasourcedummyTestraid.username")
    String userName = "";
    @Value("$spring.datasourcedummyTestraid.password")
    String password = "";
    @Autowired
    @Qualifier("jpadummyTestVendorApapter")
    JpaVendorAdapter jpadummyTestVendorApapter;

    @Bean(name = "dummyTestDataSource")
    @Primary
    public DataSource dummyTestDataSource() 
        return DataSourceBuilder.create().url(url)
                .driverClassName(driverClassName).username(userName)
                .password(password).build();
    

    @Bean
    @Primary
    public LocalContainerEntityManagerFactoryBean dummyTestEntityManagerFactory() 
        LocalContainerEntityManagerFactoryBean factoryBean = new LocalContainerEntityManagerFactoryBean();

        factoryBean.setDataSource(dummyTestDataSource());
        factoryBean.setJpaVendorAdapter(jpadummyTestVendorApapter);
        factoryBean.setPackagesToScan(R.dummyTestDB_PACKAGE);
        factoryBean.setPersistenceUnitName("dummyTestPersistenceUnit");
        factoryBean.afterPropertiesSet();

        return factoryBean;
    

    @Bean
    PlatformTransactionManager transactionManagerOne() 
        return new JpaTransactionManager(dummyTestEntityManagerFactory()
                .getObject());
    

    @Bean(name = "jpadummyTestVendorApapter")
    @Primary
    public JpaVendorAdapter jpadummyTestVendorAdapter() 
        HibernateJpaVendorAdapter jpadummyTestVendorAdapter = new HibernateJpaVendorAdapter();
        jpadummyTestVendorAdapter.setShowSql(true);
        jpadummyTestVendorAdapter.setGenerateDdl(true);
        jpadummyTestVendorAdapter.setDatabase(Database.mysql);
        return jpadummyTestVendorAdapter;
    

    @Bean
    public HibernateExceptionTranslator hibernateExceptionTranslator() 
        return new HibernateExceptionTranslator();
    


第二个数据库配置

 @Configuration
@EnableTransactionManagement
@EnableJpaRepositories(basePackages = "xx.xx.xx.xx.xx.running", entityManagerFactoryRef = "alpharaidEntityManagerFactory", transactionManagerRef = "transactionManagertwo")
@PropertySource("classpath:application.properties")
public class alphaDbConfig 

    @Value("$spring.datasourcealpharaid.driver-class-name")
    String driverClassName = "";
    @Value("$spring.datasourcealpharaid.url")
    String url = "";
    @Value("$spring.datasourcealpharaid.username")
    String userName = "";
    @Value("$spring.datasourcealpharaid.password")
    String password = "";
    @Autowired
    @Qualifier("jpaMyalphaVendorAdapter")
    JpaVendorAdapter myalphaVendorAdapter;

    @Bean(name = "alpharaidDataSource")
    public DataSource alpharaidDataSource() 
        return DataSourceBuilder.create().url(url)
                .driverClassName(driverClassName).username(userName)
                .password(password).build();
    

    @Bean
    public LocalContainerEntityManagerFactoryBean alpharaidEntityManagerFactory() 
        LocalContainerEntityManagerFactoryBean factoryBean = new LocalContainerEntityManagerFactoryBean();

        factoryBean.setDataSource(alpharaidDataSource());

        factoryBean.setJpaVendorAdapter(myalphaVendorAdapter);
        factoryBean.setPackagesToScan(R.alphaDB_PACKAGE);
        factoryBean.setPersistenceUnitName("alpharaidPersistenceUnit");
        factoryBean.afterPropertiesSet();

        return factoryBean;
    

    @Bean
    PlatformTransactionManager transactionManagerTwo() 
        return new JpaTransactionManager(alpharaidEntityManagerFactory()
                .getObject());
    

    @Bean(name = "jpaMyalphaVendorAdapter")
    public JpaVendorAdapter jpaMyalphaVendorAdapter() 
        HibernateJpaVendorAdapter jpaVendorAdapter = new HibernateJpaVendorAdapter();
        jpaVendorAdapter.setShowSql(true);
        jpaVendorAdapter.setGenerateDdl(true);
        jpaVendorAdapter.setDatabase(Database.MYSQL);
        return jpaVendorAdapter;
    


当我启动服务器时,我收到异常

    2015-08-19 15:21:25.412 ERROR 16928 --- [           main] org.hibernate.tool.hbm2ddl.SchemaUpdate  : HHH000299: Could not complete schema update

com.mysql.jdbc.exceptions.jdbc4.MySQLSyntaxErrorException: Access denied for user 'xyz'@'192.168.XX.XX' to database 'xyz'
    at sun.reflect.NativeConstructorAccessorImpl.newInstance0(Native Method)
    at sun.reflect.NativeConstructorAccessorImpl.newInstance(NativeConstructorAccessorImpl.java:62)
    at sun.reflect.DelegatingConstructorAccessorImpl.newInstance(DelegatingConstructorAccessorImpl.java:45)
    at java.lang.reflect.Constructor.newInstance(Constructor.java:422)
    at com.mysql.jdbc.Util.handleNewInstance(Util.java:377)
    at com.mysql.jdbc.Util.getInstance(Util.java:360)
    at com.mysql.jdbc.SQLError.createSQLException(SQLError.java:978)
    at com.mysql.jdbc.MysqlIO.checkErrorPacket(MysqlIO.java:3887)
    at com.mysql.jdbc.MysqlIO.checkErrorPacket(MysqlIO.java:3823)
    at com.mysql.jdbc.MysqlIO.checkErrorPacket(MysqlIO.java:870)
    at com.mysql.jdbc.MysqlIO.proceedHandshakeWithPluggableAuthentication(MysqlIO.java:1659)
    at com.mysql.jdbc.MysqlIO.doHandshake(MysqlIO.java:1206)
    at com.mysql.jdbc.ConnectionImpl.coreConnect(ConnectionImpl.java:2234)
    at com.mysql.jdbc.ConnectionImpl.connectOneTryOnly(ConnectionImpl.java:2265)
    at com.mysql.jdbc.ConnectionImpl.createNewIO(ConnectionImpl.java:2064)
    at com.mysql.jdbc.ConnectionImpl.<init>(ConnectionImpl.java:790)
    at com.mysql.jdbc.JDBC4Connection.<init>(JDBC4Connection.java:44)

和另一个在同一个异常中的(虽然稍后)

Caused by: org.springframework.beans.factory.NoUniqueBeanDefinitionException: No qualifying bean of type [javax.persistence.EntityManagerFactory] is defined: expected single matching bean but found 2: alpharaidEntityManagerFactory,dummyTestEntityManagerFactory
    at org.springframework.orm.jpa.support.PersistenceAnnotationBeanPostProcessor.findDefaultEntityManagerFactory(PersistenceAnnotationBeanPostProcessor.java:572)
    at org.springframework.orm.jpa.support.PersistenceAnnotationBeanPostProcessor.findEntityManagerFactory(PersistenceAnnotationBeanPostProcessor.java:531)
    at org.springframework.orm.jpa.support.PersistenceAnnotationBeanPostProcessor$PersistenceElement.resolveEntityManager(PersistenceAnnotationBeanPostProcessor.java:697)
    at org.springframework.orm.jpa.support.PersistenceAnnotationBeanPostProcessor$PersistenceElement.getResourceToInject(PersistenceAnnotationBeanPostProcessor.java:670)
    at org.springframework.beans.factory.annotation.InjectionMetadata$InjectedElement.inject(InjectionMetadata.java:169)
    at org.springframework.beans.factory.annotation.InjectionMetadata.inject(InjectionMetadata.java:88)
    at org.springframework.orm.jpa.support.PersistenceAnnotationBeanPostProcessor.postProcessPropertyValues(PersistenceAnnotationBeanPostProcessor.java:354)
    ... 29 more

用于读取连接详细信息的属性文件

spring.datasourcedummyTestraid.driver-class-name=com.mysql.jdbc.Driver
spring.datasourcedummyTestraid.url=jdbc:mysql://xx.xx.xx.xx/xyz
spring.datasourcedummyTestraid.username=xxx
spring.datasourcedummyTestraid.password=xxx

spring.datasourcealpharaid.driver-class-name=com.mysql.jdbc.Driver
spring.datasourcealpharaid.url=jdbc:mysql://xx.xx.xx.xx/abc
spring.datasourcealpharaid.username=xxx
spring.datasourcealpharaid.password=xxx


Few Observations:

可以看出它正在尝试连接到我的本地数据库,192.168.XX.XX 是我的本地地址。

 com.mysql.jdbc.exceptions.jdbc4.MySQLSyntaxErrorException: Access denied for user 'xyz'@'192.168.XX.XX' to database 'xyz'

(不存在),我正在尝试连接到属性文件中定义的 2 个不同的远程数据库。为什么它会转到本地?

当我评论其中一个配置时,其他配置运行良好(尽管没有出现访问问题) 的问题 No qualifying bean of type [javax.persistence.EntityManagerFactory] 为此,我尝试制作一个主要的 Bean,尝试使其功能简单但没有用。

请帮我解决问题。谢谢。

【问题讨论】:

【参考方案1】:

你可以避免这样做

@Value("$spring.datasourcealpharaid.driver-class-name")
String driverClassName = "";
@Value("$spring.datasourcealpharaid.url")
String url = "";
@Value("$spring.datasourcealpharaid.username")
String userName = "";
@Value("$spring.datasourcealpharaid.password")
String password = "";
@Autowired
@Qualifier("jpaMyAlphaVendorAdapter")
JpaVendorAdapter myAlphaVendorAdapter;

@Bean(name = "dummyTestDataSource")
public DataSource dummyTestDataSource() 
    return DataSourceBuilder.create().url(url)
            .driverClassName(driverClassName).username(userName)
            .password(password).build();

改为使用以下行来减少您的代码:

@ConfigurationProperties(prefix = "spring.datasourcealpharaid")
@Bean
@Primary
public DataSource postgresDataSource() 
    return DataSourceBuilder.create().
            build();

为了避免以下异常,您可以将 bean 命名为 entityManagerFactory

原因:org.springframework.beans.factory.NoUniqueBeanDefinitionException:没有定义 [javax.persistence.EntityManagerFactory] ​​类型的合格 bean:预期单个匹配 bean,但找到 2:macraidEntityManagerFactory,nextGenEntityManagerFactory em>

@Bean(name = "entityManagerFactory")
@Primary
public LocalContainerEntityManagerFactoryBean emf1(EntityManagerFactoryBuilder builder)
    return builder
            .dataSource(postgresDataSource())
            .packages("io.eddumelendez.springdatajpa.domain1")
            .persistenceUnit("users")
            .build();

查看完整配置here

【讨论】:

您最小化代码的建议工作正常......但不知何故其他事情不起作用

以上是关于在 Spring JPA 中连接到两个不同的数据库失败的主要内容,如果未能解决你的问题,请参考以下文章

在没有xml的spring boot中连接到mysql数据源

如何在 Spring Boot 测试中连接到内存中的 HSQLDB 以进行查询

如何在 Spring 生态系统中使用 JPA hibernate 连接到不同的 mysql 数据库模式?

在安全服务器中连接到 MongoDB

从 Spring Boot 连接到 Heroku Postgres

无法在 Spring Boot 应用程序中连接到 MongoDB