10.2.5 使用 profile 选择数据源

我们已经看到了多种在 Spring 中配置数据源的方法,我相信你已经找到了一两种适合你的应用程序的配置方式。实际上,我们很可能面临这样一种需求,那就是在某种环境下需要其中一种数据源,而在另外的环境中需要不同的数据源。

例如,对于开发期来说,<jdbc:embedded-database> 元素是很合适的,而在 QA 环境中,你可能希望使用 DBCP 的 BasicDataSource,在生产部署环境下,可能需要使 用 <jee:jndi-lookup>

我们在第 3 章所讨论的 Spring 的 bean profile 特性恰好用在这里,所需要做的就是将每个数据源配置在不同的 profile 中,如下所示:

程序清单 10.2 借助 Spring 的 profile 特性能够在运行时选择数据源
package com.habuma.spittr.config;

import org.apache.commons.dbcp.BasicDataSource;
import javax.sql.Datasource;
import org.springframework.context.annotation.Bean; 
import org.springframework.context.annotation.Configuration? 
import org.springframework.context.annotation.Profile; 
import org.springframework.jdbc.datasource.embedded.EmbeddedDatabaseBuilder; 
import org.springframework.jdbc.datasource.embedded.EmbeddedDatabaseType; 
import org.springframework.jndi.JndiObjectFactoryBean;

@Configuration
public class DataSourceConfiguration {
  @Profile("development")
  @Bean
  public DataSource embeddedDataSource() {
    return new EmbeddedDatabaseBuilder()
      .setType(EmbeddedDatabaseType.H2)
      .addScript("classpath:schema.sql")
      .addScript("classpath:test-data.sql")
      .build();
  }
  
  @Profile("qa")
  @Bean
  public DataSource Data() {
    BasicDataSource ds = new BasicDataSource();
    ds.setDriverClassName("org.h2.Driver");
    ds.setUrl("jdbc:h2:tcp://localhost/-/spitter")
    ds.setUsername("sa"); 
    ds.setPassword(""); 
    ds.setlnitialSize(5);
    ds.setMaxActive(10);
    return ds;
  }
  
  @Profile ("production")
  @Bean
  public DataSource dataSource() {
    JndiObjectFactoryBean jndiObjectFactoryBean = new JndiObjectFactoryBean();
    jndiObjectFactoryBean.setJndiName("jdbc/SpittrDS");
    jndiObjectFactoryBean.setResourceRef(true);
    jndiObjectFactoryBean.setProxylnterface(javax.sql.Datasource.class);
    return (Datasource) jndiObjectFactoryBean.getObject();
  }
}

通过使用 profile 功能,会在运行时选择数据源,这取决于哪一个 profile 处于激活状态。如程序清单 10.2 配置所示,当且仅当 development profile 处于激活状态时,会创建嵌入式数据库,当且仅当 qa profile 处于激活状态时,会创建 DBCP BasicDataSource,当且仅当 production profile 处于激活状态 时,会从 JNDI 获取数据源。

为了内容的完整性,如下的程序清单展现了如何使用 Spring XML 代替 Java 配置,实现相同的 profile 配置。

程序清单 10.3 借助 XML 配置,基于 profile 选择数据源
<?xral versions"1.0" encodings"UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
       xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
       xmlns:jdbc="http://www.springframework.org/schema/jdbc"
       xmlns:jee="http://www.springframework.org/schema/jee"
       xmlns:p="http://www.springframework.org/schetna/p"
       xsi:schemaLocation="http://www.springframework.org/schema/jdbc
           http://www.springframework.org/schema/jdbc/spring-jdbc-3.1.xsd
           http://www.sprinframework.org/schema/jee
           http://www.springframework.org/schema/jee/spring-jee-3.1.xsd
           http://www.springframework.org/schema/beans
           http://www.springframework.org/schema/beans/spring-beans.xsd">
  <beans profile="development">
    <jdbc:embedded-database id="dataSource" type="H2">
      <jdbc:script location="com/habuma/spitter/db/jdbc/schema.sql" />
      <jdbc:script location="com/habuma/spitter/db/jdbc/test-data.sql" />
    </jdbc:embedded-database>
  </beans>
  
  <beans profile="qa">
    <bean id="dataSource" classs="org.apache.commons.dbcp.BasicDataSource"
          p:driverClassName="org.h2.Driver"
          p:url="jdbc:h2:tcp://localhost/~/spitter"
          p:username="sa"
          p:password=""
          p:initialSize="5"
          p:maxActive="10" />
    </beans>
    
    <beans profile="production">
      <jee:jndi-lookup id="dataSource" jndi-name="/jdbc/SpitterDS" resource-ref="true" />
    </beans>
</beans>

现在我们已经通过数据源建立了与数据库的连接,接下来要实际访问数据库了。就像我在前面所提到的,Spring 为我们提供了多种使用数据库的方式包括 JDBC、Hibernate 以及 Java 持久化 API(Java Persistence API,JPA)。在下一节,我们将会看到如何使用 Spring 对 JDBC 的支持为应用程序构建持久层。如果你喜欢使用 Hibernate 或 JPA,那可以直接跳到下一章。

Last updated