在spring boot中连接到多个数据库
Posted
技术标签:
【中文标题】在spring boot中连接到多个数据库【英文标题】:Connecting to multiple database in spring boot 【发布时间】:2019-01-13 15:03:03 【问题描述】:我需要在我的项目中连接到两个数据库。所以我创建了两个配置文件。
@Configuration
@EnableTransactionManagement
@EnableJpaRepositories( basePackages = "com.virat.webservices.datastore.v1.Repo" )
@EntityScan("com.virat.webservices.datastore.v1.Model")
public class V1DBConfig
@Primary
@Bean( name = "dataSource" )
@ConfigurationProperties( prefix = "v1.datasource" )
public DataSource dataSource()
return DataSourceBuilder.create().build();
@Primary
@Bean( name = "entityManagerFactory" )
public LocalContainerEntityManagerFactoryBean entityManagerFactory( EntityManagerFactoryBuilder builder,
@Qualifier( "dataSource" ) DataSource dataSource )
return builder.dataSource(dataSource).packages("com.virat.webservices.datastore.v1.Model")
.persistenceUnit("db1").build();
@Primary
@Bean( name = "transactionManager" )
public PlatformTransactionManager transactionManager(
@Qualifier( "entityManagerFactory" ) EntityManagerFactory entityManagerFactory )
return new JpaTransactionManager(entityManagerFactory);
和
@Configuration
@EnableTransactionManagement
@EnableJpaRepositories( entityManagerFactoryRef = "v2EntityManagerFactory", transactionManagerRef = "v2TransactionManager", basePackages =
"com.virat.datastore.repository" )
@EntityScan( "com.virat.datastore.model" )
public class V2DBConfig
@Bean( name = "v2DataSource" )
@ConfigurationProperties( prefix = "spring.datasource" )
public DataSource dataSource()
return DataSourceBuilder.create().build();
@Bean( name = "v2EntityManagerFactory" )
public LocalContainerEntityManagerFactoryBean barEntityManagerFactory( EntityManagerFactoryBuilder builder,
@Qualifier( "v2DataSource" ) DataSource dataSource )
return builder.dataSource(dataSource).packages("com.virat.model")
.persistenceUnit("db2").build();
@Bean( name = "v2TransactionManager" )
public PlatformTransactionManager barTransactionManager(
@Qualifier( "v2EntityManagerFactory" ) EntityManagerFactory barEntityManagerFactory )
return new JpaTransactionManager(barEntityManagerFactory);
我将我的application.properties
文件配置为,
spring.datasource.type=com.zaxxer.hikari.HikariDataSource
spring.datasource.driver-class-name=com.mysql.jdbc.Driver
spring.datasource.url=jdbc:mysql://localhost:3306/db2? useUnicode=true&useJDBCCompliantTimezoneShift=true&useLegacyDatetimeCode=fal. se&serverTimezone=UTC&useSSL=false
spring.datasource.username=root
spring.datasource.password=
#spring.datasource.pool.size=20
v1.datasource.driver-class-name=com.mysql.jdbc.Driver
v1.datasource.url=jdbc:mysql://localhost:3306/db1? useUnicode=true&useJDBCCompliantTimezoneShift=true&useLegacyDatetimeCode=fal. se&serverTimezone=UTC&useSSL=false
v1.datasource.username=root
v1.datasource.password=
#v1.datasource.pool.size=20
spring.jpa.properties.hibernate.id.new_generator_mappings=false
v1.jpa.properties.hibernate.id.new_generator_mappings=false
#spring.jpa.hibernate.ddl-auto=update
spring.jpa.show-sql=true
但是当我运行应用程序时,抛出了以下异常。
***************************
APPLICATION FAILED TO START
***************************
Description:
Field entityManager in com.highpeak.tlp.webservices.services.impl.TaskServiceImpl required a single bean, but 2 were found:
- org.springframework.orm.jpa.SharedEntityManagerCreator#0: defined by method 'createSharedEntityManager' in null
- org.springframework.orm.jpa.SharedEntityManagerCreator#1: defined by method 'createSharedEntityManager' in null
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
org.springframework.boot.diagnostics.LoggingFailureAnalysisReporter org.springframework.boot.diagnostics.LoggingFailureAnalysisReporter:42 -
***************************
APPLICATION FAILED TO START
***************************
Description:
Field entityManager in com.highpeak.tlp.webservices.services.impl.TaskServiceImpl required a single bean, but 2 were found:
- org.springframework.orm.jpa.SharedEntityManagerCreator#0: defined by method 'createSharedEntityManager' in null
- org.springframework.orm.jpa.SharedEntityManagerCreator#1: defined by method 'createSharedEntityManager' in null
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
Disconnected from the target VM, address: '127.0.0.1:56875', transport: 'socket'
Process finished with exit code 1
我无法确定是什么错误。我有两个模块。一个数据库的repository
和entity
类在一个模块中,而另一个数据库的类在另一个模块中。这会导致问题吗?
编辑
我的TaskServiceImpl.java
package com.virat.webservices.services.impl;
@Service
public class TaskServiceImpl implements TaskService
private static final Logger LOGGER = LoggerFactory.getLogger(TaskServiceImpl.class);
@Autowired
@PersistenceContext(unitName = "v2EntityManagerFactory")
private EntityManager entityManager;
@Value( "$file.base.path" )
private String basePath;
@Value( "$application.domain" )
private String applicationDomain;
@Value( "$application.protocol" )
private String applicationProtocol;
@Value( "$server.port" )
private String serverPort;
@Override
@SuppressWarnings( "unchecked" )
@Transactional( rollbackOn = DataException.class )
public Integer doSomething( SomeObject someObject,
UserAccessDetails userAccessDetails ) throws DataException
try
// Do input validations
if( NullEmptyUtils.isNull(userAccessDetails) || NullEmptyUtils.isNull(someObject) )
throw new DataException(GeneralConstants.EXCEPTION, GeneralConstants.NULL_INPUT_ERROR,
HttpStatus.BAD_REQUEST);
// Creates a native mysql query based on the contents of lawyerDiscoveryParamsBean
/* Should be replaced with criteria API */
String generatedQuery = DynamicQueryGenerator.getDynamicQuery(someObject, owner);
LOGGER.info("Generated query: ", generatedQuery);
Query executableQuery = entityManager.createNativeQuery(generatedQuery, UserModel.class);
List<UserModel> userModels = executableQuery.getResultList();
if( userModels.isEmpty() )
return 0;
return 1;
catch( DataException e )
LOGGER.error(GeneralConstants.ERROR, e);
throw e;
catch( Exception e )
LOGGER.error(GeneralConstants.ERROR, e);
throw new DataException(GeneralConstants.EXCEPTION, GeneralConstants.SOMETHING_WENT_WRONG,
HttpStatus.INTERNAL_SERVER_ERROR);
【问题讨论】:
能否请您加入TaskServiceImpl
?
@Dan 添加了课程
你看过这个问题的答案了吗:***.com/questions/45663025/…
这是另一个值得检查的好资源:roufid.com/spring-boot-multiple-databases-configuration
【参考方案1】:
在您的TaskServiceImpl
中确保您正确注释了 persistenceContext。
例如:
@PersistenceContext(unitName = "entityManagerFactory")
private EntityManager em;
【讨论】:
我采用了同样的方法。但是,现在例外说,Bean named 'v2DataSource' is expected to be of type 'javax.persistence.EntityManagerFactory' but was actually of type 'org.apache.tomcat.jdbc.pool.DataSource'
试过了。它给出了问题中发布的原始异常
删除 @Autowired
之前的 @PersistenceContext
注释
谢谢@Dan。我犯了答案中指定的一些错误。我错了,我都没有正确命名。【参考方案2】:
在V1DBConfig.java
中,注解@EnableJpaRepository
其实应该是这样的,
@EnableJpaRepositories( entityManagerFactoryRef = "entityManagerFactory", transactionManagerRef = "transactionManager", basePackages =
"com.virat.webservices.datastore.v1.Repo" )
您已经在V2DBConfig.java
类中完成了配置(查看@EnableJpaRepository
注释)。在V1DBConfig.java
中做同样的事情。
然后,在您的TaskServiceImpl.java
中,提供PersistenceContext
,由@Dan 回答。我希望这会有所帮助。
【讨论】:
以上是关于在spring boot中连接到多个数据库的主要内容,如果未能解决你的问题,请参考以下文章
如何在 Spring Boot 测试中连接到内存中的 HSQLDB 以进行查询
无法在 Spring Boot 应用程序中连接到 MongoDB
Spring Boot Docker Container 无法连接到托管在 Docker 主机上的 postgresql