【问题标题】:In Spring-Boot, How can we connect to two databases (Mysql database and MongoDB) in the same project?在 Spring-Boot 中,我们如何在同一个项目中连接两个数据库(Mysql 数据库和 MongoDB)?
【发布时间】: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?我不需要做任何额外的事情吗?
  • 是的,这是自动发生的,不,如果你这样做,你不必添加任何其他东西。

标签: java mysql spring mongodb spring-boot


【解决方案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 方法和相应的注释
猜你喜欢
  • 1970-01-01
  • 2019-08-10
  • 2018-11-08
  • 1970-01-01
  • 2017-06-11
  • 2019-01-17
  • 1970-01-01
  • 2021-03-11
  • 1970-01-01
相关资源
最近更新 更多