在 Spring-Boot 中,我们如何在同一个项目中连接两个数据库(Mysql 数据库和 MongoDB)?

Posted

技术标签:

【中文标题】在 Spring-Boot 中,我们如何在同一个项目中连接两个数据库(Mysql 数据库和 MongoDB)?【英文标题】:In Spring-Boot, How can we connect to two databases (Mysql database and MongoDB) in the same project? 【发布时间】:2015-12-25 13:48:09 【问题描述】:

我正在尝试创建一个“Spring-Boot”项目,在该项目中我需要连接到不同的数据库“mysql”和“MongoDB”。

我是否需要做一些特殊的事情来连接到两个数据库,否则 spring-boot 会自动连接到两个数据库。我还需要为“mongodb”定义数据源吗?

MySQL 特定的“YML”文件如下所示

# Default DB parameter definitions for the URL parameters in the spring.datasource.url property below
database:
  host: localhost
  port: 3306
  schema: subscriptions
  username: root
  password: root
  autoconnect:
    maxReconnects: 3
    initialTimeout: 2
  timeout:
    connectTimeout: 0
    socketTimeout: 0
  failover:
    host: localhost 
    port: 3306
    queriesBeforeRetryMaster: 50
    secondsBeforeRetryMaster: 30
  properties: useTimezone=true&serverTimezone=UTC&useLegacyDatetimeCode=false&failOverReadOnly=false&autoReconnect=true&maxReconnects=$database.autoconnect.maxReconnects&initialTimeout=$database.autoconnect.initialTimeout&connectTimeout=$database.timeout.connectTimeout&socketTimeout=$database.timeout.socketTimeout&queriesBeforeRetryMaster=$database.failover.queriesBeforeRetryMaster&secondsBeforeRetryMaster=$database.failover.secondsBeforeRetryMaster

spring:
  datasource:
    driverClassName: com.mysql.jdbc.Driver
    url: jdbc:mysql://$database.host:$database.port,$database.failover.host:$database.failover.port/$database.schema?$database.properties
    username: $database.username
    password: $database.password
    continueOnError: true
    initialize: false
    initialSize: 0
    timeBetweenEvictionRunsMillis: 5000
    minEvictableIdleTimeMillis: 5000
    removeAbandonedTimeout: 60
    removeAbandoned: true
    minIdle: 0

  jpa:
    show-sql: true
    hibernate:
      ddl-auto: none
      naming_strategy: org.hibernate.cfg.DefaultNamingStrategy
    properties:
      hibernate:
        dialect: org.hibernate.dialect.MySQL5Dialect
        hbm2ddl:
          auto: none
        temp:
          use_jdbc_metadata_defaults: false 

我的 MongoDB“YML”如下所示

spring:
  data:
    mongodb.host: localhost
    mongodb.port: 27017
    mongodb.database: eventsarchive
    mongodb.username: root
    mongodb.password: root
    mongodb.repositories.enabled: true

Application.java 文件如下

@Configuration
@EnableAutoConfiguration
@EnableConfigurationProperties
@EntityScan(basePackages =  "persistence.mysql.domain" )
@EnableJpaRepositories("persistence.mysql.dao")
@EnableMongoRepositories("persistence.mongodb.dao")
@ComponentScan(excludeFilters =  @ComponentScan.Filter(type = FilterType.ASSIGNABLE_TYPE,
value = ApiAuthenticationFilter.class) ,
basePackages = 
                "admin",
                "common",
                "mqclient",
"scheduler" )
public class Application 

  @Value("$service.name")
  private String serviceName;
  @Value("$service.namespace")
  private String serviceNamespace;
  @Value("$webservice.namespace")
  private String webserviceNamespace;
  @Value("$webservice.port")
  private int webservicePort;
  @Value("$jersey.request-filters")
  private String requestFilters;
  @Value("$jersey.response-filters")
  private String responseFilters;

  private static final String MAPPING_URL = "/%s/*";

  static 
    System.setProperty(USER_TIMEZONE, "UTC");
  

  /**
   * Java main method.
   */
  public static void main(String[] args) 
    /*
     * Defines which Spring Boot Profiles should be active on startup. Please see
     * http://docs.spring.io/spring-boot/docs/current/reference/htmlsingle/#boot-features-profiles for details.
     */
    final SpringApplicationBuilder appBuilder = new SpringApplicationBuilder(Application.class);
    appBuilder.profiles("common", "common_mongo_db", "common_mysql_db", "common_rabbitmq", "admin").application()
    .run(args);
  

  /**
   * Registers Jersey with Spring Boot.
   */
  @Bean
  public ServletRegistrationBean registerJersey() 
    final ServletRegistrationBean registration = new ServletRegistrationBean(new SpringServlet(),
                                                                             String.format(MAPPING_URL,
                                                                                           this.serviceNamespace));

    registration.addInitParameter(JERSEY_MAPPING_FEATURE, Boolean.toString(true));
    registration.addInitParameter(PROPERTY_CONTAINER_REQUEST_FILTERS, this.requestFilters);
    registration.addInitParameter(PROPERTY_CONTAINER_RESPONSE_FILTERS, this.responseFilters);
    registration.addInitParameter(PROPERTY_RESOURCE_FILTER_FACTORIES, ValidationResourceFilterFactory.class.getName());

    return registration;
  

  /**
   * This method initializes SimpleHttpServerJaxWsServiceExporter bean which reads all @Webservice annotated components
   * and hosts web service for them.
   *
   * @return SimpleHttpServerJaxWsServiceExporter
   */
  @Bean
  public SimpleHttpServerJaxWsServiceExporter exportJaxwsService() 
    final SimpleHttpServerJaxWsServiceExporter jaxWsServiceExporter = new SimpleHttpServerJaxWsServiceExporter();
    jaxWsServiceExporter.setPort(this.webservicePort);
    jaxWsServiceExporter.setBasePath("/" + this.serviceNamespace + "/" + this.webserviceNamespace + "/");
    return jaxWsServiceExporter;
  

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

  @Bean
  public EmbeddedServletContainerFactory servletContainer() 
    TomcatEmbeddedServletContainerFactory factory = new TomcatEmbeddedServletContainerFactory();
    factory.setTomcatContextCustomizers(Arrays.asList(new CustomCustomizer()));
    return factory;
  

  static class CustomCustomizer implements TomcatContextCustomizer 

    @Override
    public void customize(Context context) 
      context.setUseHttpOnly(false);
      context.setCookies(false);
    
  

【问题讨论】:

那么不清楚您的问题是什么?为了连接数据库,您提供了一切必要的东西。您是否更质疑如何从/向哪个数据库读取/写入?这取决于您遵循的模型。如果您使用存储库,这由您用于继承的父接口定义,JpaRepositoryMongoRepository 你是说Spring boot会根据JpaRepository或者MongoRepository这样的repository自动切换mongoDb和mysql?我不需要做任何额外的事情吗? 是的,这是自动发生的,不,如果你这样做,你不必添加任何其他东西。 【参考方案1】:

这个论坛没有关于在同一个spring-boot项目中连接两个不同数据库(Mysql数据库和MongoDB)的问题。

我已经完成了这项工作,因此我将其作为答案发布在这里。

根据特定存储库所属的数据库,使用以下给定配置和存储库作为 JpaRepository 或 MongoRepository。

MySQL 特定的“YML”文件如下所示

# Default DB parameter definitions for the URL parameters in the spring.datasource.url property below
database:
  host: localhost
  port: 3306
  schema: subscriptions
  username: root
  password: root
  autoconnect:
    maxReconnects: 3
    initialTimeout: 2
  timeout:
    connectTimeout: 0
    socketTimeout: 0
  failover:
    host: localhost 
    port: 3306
    queriesBeforeRetryMaster: 50
    secondsBeforeRetryMaster: 30
  properties: useTimezone=true&serverTimezone=UTC&useLegacyDatetimeCode=false&failOverReadOnly=false&autoReconnect=true&maxReconnects=$database.autoconnect.maxReconnects&initialTimeout=$database.autoconnect.initialTimeout&connectTimeout=$database.timeout.connectTimeout&socketTimeout=$database.timeout.socketTimeout&queriesBeforeRetryMaster=$database.failover.queriesBeforeRetryMaster&secondsBeforeRetryMaster=$database.failover.secondsBeforeRetryMaster

spring:
  datasource:
    driverClassName: com.mysql.jdbc.Driver
    url: jdbc:mysql://$database.host:$database.port,$database.failover.host:$database.failover.port/$database.schema?$database.properties
    username: $database.username
    password: $database.password
    continueOnError: true
    initialize: false
    initialSize: 0
    timeBetweenEvictionRunsMillis: 5000
    minEvictableIdleTimeMillis: 5000
    removeAbandonedTimeout: 60
    removeAbandoned: true
    minIdle: 0
  
  jpa:
    show-sql: true
    hibernate:
      ddl-auto: none
      naming_strategy: org.hibernate.cfg.DefaultNamingStrategy
    properties:
      hibernate:
        dialect: org.hibernate.dialect.MySQL5Dialect
        hbm2ddl:
          auto: none
        temp:
          use_jdbc_metadata_defaults: false 

我的 MongoDB“YML”如下所示

spring:
  data:
    mongodb.host: localhost
    mongodb.port: 27017
    mongodb.database: eventsarchive
    mongodb.username: root
    mongodb.password: root
    mongodb.repositories.enabled: true

Application.java 文件如下

@Configuration
@EnableAutoConfiguration
@EnableConfigurationProperties
@EntityScan(basePackages =  "persistence.mysql.domain" )
@EnableJpaRepositories("persistence.mysql.dao")
@EnableMongoRepositories("persistence.mongodb.dao")
@ComponentScan(excludeFilters =  @ComponentScan.Filter(type = FilterType.ASSIGNABLE_TYPE,
value = ApiAuthenticationFilter.class) ,
basePackages = 
                "admin",
                "common",
                "mqclient",
"scheduler" )
public class Application 

  @Value("$service.name")
  private String serviceName;
  @Value("$service.namespace")
  private String serviceNamespace;
  @Value("$webservice.namespace")
  private String webserviceNamespace;
  @Value("$webservice.port")
  private int webservicePort;
  @Value("$jersey.request-filters")
  private String requestFilters;
  @Value("$jersey.response-filters")
  private String responseFilters;

  private static final String MAPPING_URL = "/%s/*";

  static 
    System.setProperty(USER_TIMEZONE, "UTC");
  

  /**
   * Java main method.
   */
  public static void main(String[] args) 
    /*
     * Defines which Spring Boot Profiles should be active on startup. Please see
     * http://docs.spring.io/spring-boot/docs/current/reference/htmlsingle/#boot-features-profiles for details.
     */
    final SpringApplicationBuilder appBuilder = new SpringApplicationBuilder(Application.class);
    appBuilder.profiles("common", "common_mongo_db", "common_mysql_db", "common_rabbitmq", "admin").application()
    .run(args);
  

  /**
   * Registers Jersey with Spring Boot.
   */
  @Bean
  public ServletRegistrationBean registerJersey() 
    final ServletRegistrationBean registration = new ServletRegistrationBean(new SpringServlet(),
                                                                             String.format(MAPPING_URL,
                                                                                           this.serviceNamespace));

    registration.addInitParameter(JERSEY_MAPPING_FEATURE, Boolean.toString(true));
    registration.addInitParameter(PROPERTY_CONTAINER_REQUEST_FILTERS, this.requestFilters);
    registration.addInitParameter(PROPERTY_CONTAINER_RESPONSE_FILTERS, this.responseFilters);
    registration.addInitParameter(PROPERTY_RESOURCE_FILTER_FACTORIES, ValidationResourceFilterFactory.class.getName());

    return registration;
  

  /**
   * This method initializes SimpleHttpServerJaxWsServiceExporter bean which reads all @Webservice annotated components
   * and hosts web service for them.
   *
   * @return SimpleHttpServerJaxWsServiceExporter
   */
  @Bean
  public SimpleHttpServerJaxWsServiceExporter exportJaxwsService() 
    final SimpleHttpServerJaxWsServiceExporter jaxWsServiceExporter = new SimpleHttpServerJaxWsServiceExporter();
    jaxWsServiceExporter.setPort(this.webservicePort);
    jaxWsServiceExporter.setBasePath("/" + this.serviceNamespace + "/" + this.webserviceNamespace + "/");
    return jaxWsServiceExporter;
  

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

  @Bean
  public EmbeddedServletContainerFactory servletContainer() 
    TomcatEmbeddedServletContainerFactory factory = new TomcatEmbeddedServletContainerFactory();
    factory.setTomcatContextCustomizers(Arrays.asList(new CustomCustomizer()));
    return factory;
  

  static class CustomCustomizer implements TomcatContextCustomizer 

    @Override
    public void customize(Context context) 
      context.setUseHttpOnly(false);
      context.setCookies(false);
    
  

【讨论】:

对我来说不同的是 primaryDatasource 方法和相应的注释

以上是关于在 Spring-Boot 中,我们如何在同一个项目中连接两个数据库(Mysql 数据库和 MongoDB)?的主要内容,如果未能解决你的问题,请参考以下文章

如何在 spring-boot 中配置 Jetty(很容易?)

在 Spring-Boot 中,我们如何在同一个项目中连接两个数据库(Mysql 数据库和 MongoDB)?

Spring-Boot配置项

spring-boot 速成 自定义配置

Spring-boot - 如何同时使用 Resteasy JAX-RS 和 Spring MVC 控制器

Spring-boot千分尺定时器()它是如何工作的?