2016-10-04 6 views
0

Я довольно новичок в Spring Framework, и у меня возникли проблемы с настройкой проекта, над которым я сейчас работаю. Мне нужно иметь возможность подключаться к двум различным базам данных: MongoDB, а другой - MSSQL. Я использую JPA для подключения к MSSQL.Весна, использующая реализацию Монго по JPA

Проблема, с которой я сталкиваюсь, заключается в том, что она пытается совершать вызовы в базу данных Mongo, когда я хочу, чтобы она вызывала вызовы MSSQL, и я не уверен, как сказать ей, что читать. Я видел сообщения, которые советуют использовать аннотацию @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.

Выездное поток показывает только «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 для конкретного репозитория или вызова базы данных?

ответ

1

Вы можете подключаться к различным базам данных весной на основе конфигурации в контексте.

Данный код предназначен для подключения к MySql и Mongo DB. Вы можете заменить MySql на MSSQL, если у вас есть 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 --> 

Теперь вы можете использовать репозитории, предоставляемые весной.

EDIT 1: Предположим, что имя конфигурации - springConfig.properties. В приведенном выше примере для свойств dbname, хоста и порта в mongo: db-factory, вы хотите, чтобы значения были настроены в 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> 

боб Монго: DB-завод теперь будет выглядеть так:

<mongo:db-factory dbname="${mongoDb}" host="${mongoServer}" port="${mongoPort}"/> 

Обратите внимание, что «ключи» от конфигурации (DbName, хост и порт) представлены insde $ {}. Это заменит значения в конфиге для ключей.

+0

Спасибо! Знаете ли вы, что есть хороший ресурс в Интернете для «перевода» Java Config в XML. Я искал довольно давно и ничего не придумал. XML просто кажется более чистым, и мы уже используем его для реализации Mongo. – CraigR8806

+0

Если вы имеете в виду получение значения из конфигурации и обновления в xml при загрузке программы, то редактирование в приведенном выше поможет. – HARDI

0

Для JPA необходимо иметь две разделенные конфигурации. Не забудьте отключить автоматическую настройку JPA.

@SpringBootApplication(
     exclude={ 
      DataSourceAutoConfiguration.class, 
      DataSourceTransactionManagerAutoConfiguration.class, 
      HibernateJpaAutoConfiguration.class 
     } 
) 

Ниже приведен пример для двух разных баз данных sql. Может быть легко адаптирован для ваших нужд (когда вторым источником данных является монго).

Первых один:

@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 дб

Но хранилища из пакета co.sellit.core.api.repository.openfire будут использовать openfire базы данных.

UPDATE (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" /> 
+0

Спасибо за ответ, однако я думаю, что мы пытаемся придерживаться конфигурации XML. – CraigR8806

+0

Я обновил свой ответ с помощью xml config. Идея схожа. –

Смежные вопросы