我是Spring Framework的新手,并且在设置我正在进行的项目时遇到了一些麻烦。我需要能够连接到两个不同的数据库,一个是MongoDB,另一个是MSSQL。我正在使用JPA连接到MSSQL。
我遇到的问题是,当我希望它调用MSSQL时,它似乎试图调用Mongo数据库,我不确定如何告诉它要读什么。我已经看到帖子建议使用@Qualifier
注释将其指向正确的实现,但我不认为这对我的情况有用。
@RestController
@RequestMapping("/software")
public class SoftwareEndpoint {
@Autowired
SoftwareRepository repo;
/**********************************************************************************
********************************MSSQL calls****************************************
***********************************************************************************/
@RequestMapping(value="/all",method=RequestMethod.GET,produces=MediaType.APPLICATION_JSON)
String getAllSoftware(){
System.out.println("Here1");
List<Software> allSoftware = (List<Software>) repo.findAll();
System.out.println("Here2");
//rest of method and class
上面显示了我的控制器类的片段,其中包含我的SoftwareRepository实例。我也会在db调用之前和之后打印到out stream。
出流只显示“Here1”,继续打印出这一行:
2016-10-04 07:35:39.810 INFO 4236 --- [nio-8080-exec-2] org.mongodb.driver.cluster : No server chosen by ReadPreferenceServerSelector{readPreference=primary} from cluster description ClusterDescription{type=UNKNOWN, connectionMode=SINGLE, all=[ServerDescription{address=localhost:27017, type=UNKNOWN, state=CONNECTING, exception={com.mongodb.MongoSocketOpenException: Exception opening socket}, caused by {java.net.ConnectException: Connection refused: connect}}]}. Waiting for 30000 ms before timing out
然后在超时时抛出异常。
我没有在本地运行的mongo实例,但是会有应用程序部署的位置,但我不相信这是问题,因为在点击该端点时,它不应该进行调用到Mongo数据库,应该尝试联系MSSQL。
TLDR:如何指定Spring用于特定存储库或数据库调用的数据库实现?
答案 0 :(得分:1)
您可以根据上下文中的配置在spring中连接到不同的数据库。
以下代码用于连接MySql和Mongo DB。你可以用MySQL替换MySql,前提是你有JDBC。检查http://jdbforms.sourceforge.net/UsersGuide/html/ch20s02.html,了解JDBC连接的属性是什么意思。
<bean id="jdbcTemplate" class="org.springframework.jdbc.core.JdbcTemplate">
<constructor-arg ref="mySqldataSource" /> <!-- Change the datasource to MSSQL-->
</bean>
<bean id="mySqldataSource" class="org.apache.commons.dbcp.BasicDataSource"
destroy-method="close">
<property name="removeAbandoned">
<value>true</value>
</property>
<property name="removeAbandonedTimeout">
<value>30</value>
</property>
<property name="driverClassName">
<value>MSSQL_DRIVER_CLASS_NAME</value>
</property>
<property name="url">
<value>MSSQL_DATABASE_URL</value>
</property>
<property name="username">
<value>MSSQL_DB_USER_NAME</value>
</property>
<property name="password">
<value>MSSQL_DB_PASSWORD</value>
</property>
<property name="maxIdle">
<value>10</value>
</property>
<property name="maxActive">
<value>10</value>
</property>
<property name="maxWait">
<value>100000</value>
</property>
<property name="testOnBorrow">
<value>false</value>
</property>
<property name="testWhileIdle">
<value>false</value>
</property>
<property name="timeBetweenEvictionRunsMillis">
<value>60000</value>
</property>
<property name="minEvictableIdleTimeMillis">
<value>60000</value>
</property>
<property name="numTestsPerEvictionRun">
<value>1</value>
</property>
<property name="defaultTransactionIsolation" value="1" />
<property name="poolPreparedStatements" value="true" />
<property name="maxOpenPreparedStatements" value="1" />
</bean>
<bean class="org.apache.commons.dbcp.BasicDataSource" destroy-method="close"></bean>
以下是连接到mongodb
<mongo:db-factory dbname="mongoDbName" host="mongoServer" port="mongoPort"/>
<bean id="mongoTemplate" class="org.springframework.data.mongodb.core.MongoTemplate">
<constructor-arg name="mongoDbFactory" ref="mongoDbFactory" />
</bean>
<mongo:repositories base-package="com.test.repoPackage"/> <!-- Package containing the mongo repository interfaces -->
现在您可以使用spring提供的存储库。
编辑1:假设配置名称为springConfig.properties。在mongo:db-factory中属性dbname,host和port的上面示例中,您希望在springConfig.properties中配置值。所以我们在下面命名:
mongoServer = xxx.xx.xxx.xxx
mongoPort = 27017
mongoDb = testDb
现在需要修改上下文文件以导入springConfig.properties。这在上下文文件中完成:
<bean id="propertyConfigurer"
class="org.springframework.beans.factory.config.PropertyPlaceholderConfigurer" >
<property name="locations" >
<list>
<value>classpath:/log4j.properties</value>
<value>classpath:/springConfig.properties</value>
</list>
</property>
</bean>
bean mongo:db-factory现在看起来像:
<mongo:db-factory dbname="${mongoDb}" host="${mongoServer}" port="${mongoPort}"/>
请注意,config(dbname,host和port)中的“keys”表示为$ {}。这将替换为配置中的键值。
答案 1 :(得分:0)
您需要为JPA分配两个独立的配置。不要忘记禁用JPA自动配置。
@SpringBootApplication(
exclude={
DataSourceAutoConfiguration.class,
DataSourceTransactionManagerAutoConfiguration.class,
HibernateJpaAutoConfiguration.class
}
)
下面是两个不同的sql数据库的示例。可以很容易地适应您的需求(当第二个数据源是mongo时)。
第一个:
@Configuration
@EnableTransactionManagement
@EnableJpaRepositories(
entityManagerFactoryRef = "sellitEntityManagerFactory",
transactionManagerRef = "sellitTransactionManager",
basePackages = { "co.sellit.core.api.repository.sellit" }
)
public class JpaSellitConfig {
@Bean
@ConfigurationProperties(prefix="spring.datasource.sellit")
public DataSourceProperties sellitDataSourceProperties() {
return new DataSourceProperties();
}
@Bean
@ConfigurationProperties(prefix="spring.hikaricp.sellit")
public HikariConfig sellitHikariConfig() {
HikariConfig hikariConfig = new HikariConfig();
return hikariConfig;
}
@Bean
public DataSource sellitDataSource(
@Qualifier("sellitHikariConfig") HikariConfig sellitHikariConfig,
@Qualifier("sellitDataSourceProperties") DataSourceProperties sellitDataSourceProperties) {
sellitHikariConfig.setDriverClassName(sellitDataSourceProperties.getDriverClassName());
sellitHikariConfig.setJdbcUrl(sellitDataSourceProperties.getUrl());
sellitHikariConfig.setUsername(sellitDataSourceProperties.getUsername());
sellitHikariConfig.setPassword(sellitDataSourceProperties.getPassword());
sellitHikariConfig.setConnectionTestQuery("SELECT 1");
HikariDataSource hikariDataSource = new HikariDataSource(sellitHikariConfig);
return hikariDataSource;
}
@Bean
@ConfigurationProperties(prefix="spring.jpa.sellit")
public JpaVendorAdapter sellitJpaVendorAdapter() {
HibernateJpaVendorAdapter jpaVendorAdapter = new HibernateJpaVendorAdapter();
return jpaVendorAdapter;
}
@Bean
@Autowired
public EntityManagerFactory sellitEntityManagerFactory(
@Qualifier("sellitDataSource") DataSource sellitDataSource,
@Qualifier("sellitJpaVendorAdapter") JpaVendorAdapter sellitJpaVendorAdapter) {
LocalContainerEntityManagerFactoryBean lemf = new LocalContainerEntityManagerFactoryBean();
lemf.setDataSource(sellitDataSource);
lemf.setJpaVendorAdapter(sellitJpaVendorAdapter);
lemf.setPackagesToScan("co.sellit.core.api.entity.sellit");
lemf.setPersistenceUnitName("sellitPersistenceUnit");
lemf.afterPropertiesSet();
return lemf.getObject();
}
@Bean
@Autowired
public EntityManager sellitDataSourceEntityManager(
@Qualifier("sellitEntityManagerFactory") EntityManagerFactory sellitEntityManagerFactory) {
return sellitEntityManagerFactory.createEntityManager();
}
@Bean
@Autowired
@Qualifier("sellitTransactionManager")
public PlatformTransactionManager sellitTransactionManager(
@Qualifier("sellitEntityManagerFactory") EntityManagerFactory sellitEntityManagerFactory) {
return new JpaTransactionManager(sellitEntityManagerFactory);
}
}
第二个:
@Configuration
@EnableTransactionManagement
@EnableJpaRepositories(
entityManagerFactoryRef = "ofEntityManagerFactory",
transactionManagerRef = "ofTransactionManager",
basePackages = { "co.sellit.core.api.repository.openfire" }
)
public class JpaOpenfireConfig {
@Bean
@ConfigurationProperties(prefix="spring.datasource.openfire")
public DataSourceProperties ofDataSourceProperties() {
return new DataSourceProperties();
}
@Bean
@ConfigurationProperties(prefix="spring.hikaricp.openfire")
public HikariConfig ofHikariConfig() {
HikariConfig hikariConfig = new HikariConfig();
return hikariConfig;
}
@Bean
public DataSource ofDataSource(
@Qualifier("ofHikariConfig") HikariConfig ofHikariConfig,
@Qualifier("ofDataSourceProperties") DataSourceProperties ofDataSourceProperties) {
ofHikariConfig.setDriverClassName(ofDataSourceProperties.getDriverClassName());
ofHikariConfig.setJdbcUrl(ofDataSourceProperties.getUrl());
ofHikariConfig.setUsername(ofDataSourceProperties.getUsername());
ofHikariConfig.setPassword(ofDataSourceProperties.getPassword());
ofHikariConfig.setConnectionTestQuery("SELECT 1");
HikariDataSource hikariDataSource = new HikariDataSource(ofHikariConfig);
return hikariDataSource;
}
@Bean
@ConfigurationProperties(prefix="spring.jpa.openfire")
public JpaVendorAdapter ofJpaVendorAdapter() {
HibernateJpaVendorAdapter jpaVendorAdapter = new HibernateJpaVendorAdapter();
return jpaVendorAdapter;
}
@Bean
@Autowired
public EntityManagerFactory ofEntityManagerFactory(
@Qualifier("ofDataSource") DataSource ofDataSource,
@Qualifier("ofJpaVendorAdapter") JpaVendorAdapter ofJpaVendorAdapter) {
LocalContainerEntityManagerFactoryBean lemf = new LocalContainerEntityManagerFactoryBean();
lemf.setDataSource(ofDataSource);
lemf.setJpaVendorAdapter(ofJpaVendorAdapter);
lemf.setPackagesToScan("co.sellit.core.api.entity.openfire");
lemf.setPersistenceUnitName("ofPersistenceUnit");
lemf.afterPropertiesSet();
return lemf.getObject();
}
@Bean
@Autowired
public EntityManager ofDataSourceEntityManager(
@Qualifier("ofEntityManagerFactory") EntityManagerFactory ofEntityManagerFactory) {
return ofEntityManagerFactory.createEntityManager();
}
@Bean
@Autowired
@Qualifier("ofTransactionManager")
public PlatformTransactionManager ofTransactionManager(
@Qualifier("ofEntityManagerFactory") EntityManagerFactory ofEntityManagerFactory) {
return new JpaTransactionManager(ofEntityManagerFactory);
}
}
所以来自包co.sellit.core.api.repository.sellit
的存储库将使用sellit
db
但是包co.sellit.core.api.repository.openfire
中的存储库将使用openfire
数据库。
更新(xml配置版本)
<bean id="openfireDataSource" class="org.springframework.jdbc.datasource.DriverManagerDataSource">
<property name="driverClassName" value="com.mysql.jdbc.Driver" />
<property name="url" value="jdbc:mysql://localhost:3306/openfire?characterEncoding=UTF-8" />
</bean>
<bean id="sellitDataSource" class="org.springframework.jdbc.datasource.DriverManagerDataSource">
<property name="driverClassName" value="com.mysql.jdbc.Driver" />
<property name="url" value="jdbc:mysql://localhost:3306/sellit?characterEncoding=UTF-8" />
</bean>
<bean id="openfireSessionFactory" class="org.springframework.orm.hibernate4.LocalSessionFactoryBean">
<property name="dataSource" ref="openfireDataSource" />
<property name="packagesToScan" value="co.sellit.core.api.repository.openfire" />
<property name="hibernateProperties">
<props>
...
</props>
</property>
</bean>
<bean id="sellitSessionFactory" class="org.springframework.orm.hibernate4.LocalSessionFactoryBean">
<property name="dataSource" ref="sellitDataSource" />
<property name="packagesToScan" value="co.sellit.core.api.repository.sellit" />
<property name="hibernateProperties">
<props>
...
</props>
</property>
</bean>
<bean id="openfireTxnManager" class="org.springframework.orm.hibernate4.HibernateTransactionManager">
<property name="sessionFactory" ref="openfireSessionFactory" />
</bean>
<bean id="sellitTxnManager" class="org.springframework.orm.hibernate4.HibernateTransactionManager">
<property name="sessionFactory" ref="sellitSessionFactory" />
</bean>
<tx:annotation-driven transaction-manager="openfireTxnManager" />
<tx:annotation-driven transaction-manager="sellitTxnManager" />