总结:
最近在做 webMagic 的后台, 遇到一个问题: 后台用到了数据库, 本来理想情况下是用 MySQL, 但是为了做到开箱即用, 也整合了一个嵌入式数据库 H2. 这里面就有个问题了, 如何用一套代码, 提供对 MySQL 和 H2 两种方案的支持? 博主收集了一些资料, 也调试了很久, 终于找到一套可行方案, 记录下来. 代码贴的有点多, 主要是为了以后方便自己查找.
H2 的使用
H2 是一个嵌入式, 纯 Java 实现的数据库, 它各方面都要好于 Java 的 sqlitejdbc. 它可以使用内存模式, 也可以使用磁盘模式. 具体使用可以看攻略:
http://www.cnblogs.com/gao241/p/3480472.html
为 MyBatis 同时配置两套数据源
我们希望达到的效果是, 不同的数据源使用不同的 sql, 并且这个切换最好只在配置中体现, 与代码无关. 所以我们选择 xml 的方式编写 sql 语句.
MyBatis Spring 的使用
同时使用 Mybatis-Spring 插件, 这样 Mybatis 可以将 Mapper(也就是 DAO) 自动配置成 Bean, 非常方便. 它的一个完整示例可以看这个项目: https://GitHub.com/mybatis/jpetstore-6. 这里我配置如下:
配置 Bean
- <bean class="org.mybatis.spring.mapper.MapperScannerConfigurer">
- <property name="basePackage" value="us.codecraft.webmagic.dao" />
- </bean>
- <bean id="sqlSessionFactory" class="org.mybatis.spring.SqlSessionFactoryBean">
- <property name="dataSource" ref="dataSource" />
- <property name="mapperLocations" value="classpath*:/config/mapper/*/.xml"
- />
- </bean>
配置 Mapper
对应的 DAO 和配置文件如下:
- us.codecraft.webmagic.dao.DynamicClassDao: public interface DynamicClassDao {
- public int add(DynamicClass dynamicClass);
- }
DynamicClassDao.xml
- <mapper namespace="us.codecraft.webmagic.dao.DynamicClassDao">
- <insert id="add" parameterType="us.codecraft.webmagic.model.DynamicClass">
- insert into DynamicClass (`ClassName`,`SourceCode`,`AddTime`,`UpdateTime`)
- values (#{className},#{sourceCode},now(),now())
- </insert>
- </mapper>
使用 databaseIdProvider 进行多个数据源的 SQL 切换
MyBatis 支持根据不同的数据库名来进行 SQL 语句的切换. 做法是初始化 SqlSessionFactoryBean 的时候, 配置一个 databaseIdProvider.
- <bean id="vendorProperties" class="org.springframework.beans.factory.config.PropertiesFactoryBean">
- <property name="properties">
- <props>
- <prop key="SQL Server">
- sqlserver
- </prop>
- <prop key="DB2">
- db2
- </prop>
- <prop key="Oracle">
- oracle
- </prop>
- <prop key="MySQL">
- MySQL
- </prop>
- <prop key="H2">
- h2
- </prop>
- </props>
- </property>
- </bean>
- <bean id="databaseIdProvider" class="org.apache.ibatis.mapping.VendorDatabaseIdProvider">
- <property name="properties" ref="vendorProperties" />
- </bean>
- <bean id="sqlSessionFactory" class="org.mybatis.spring.SqlSessionFactoryBean">
- <property name="dataSource" ref="dataSource" />
- <property name="databaseIdProvider" ref="databaseIdProvider" />
- <property name="mapperLocations" value="classpath*:/config/mapper/*/.xml"
- />
- </bean>
然后在 Mapper 的 xml 里, 把相应的语句加上 databaseId="xxx" 就可以了.
- <!DOCTYPE mapper PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN" "http://mybatis.org/dtd/mybatis-3-mapper.dtd">
- http://mybatis.org/dtd/mybatis-3-mapper.dtd ;
- <mapper namespace="us.codecraft.webmagic.dao.DynamicClassDao">
- <insert id="add" parameterType="us.codecraft.webmagic.model.DynamicClass"
- databaseId="MySQL">
- insert into DynamicClass (`ClassName`,`SourceCode`,`AddTime`,`UpdateTime`)
- values (#{className},#{sourceCode},now(),now())
- </insert>
- <insert id="add" parameterType="us.codecraft.webmagic.model.DynamicClass"
- databaseId="h2">
- insert into DynamicClass (`ClassName`,`SourceCode`,`AddTime`,`UpdateTime`)
- values (#{className},#{sourceCode},now(),now())
- </insert>
- </mapper>
- Spring Profile
Profile 是 Spring 3.1 后新增的特性, 简单来说, 就是根据不同的环境, 读取不同的配置. 这些配置可以放在一起, 但是单独生效. 贴个代码吧, 很容易说明问题了:
- <?xml version="1.0" encoding="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"
- xsi:schemaLocation=" http://www.springframework.org/schema/beans
- http://www.springframework.org/schema/jdbc http://www.springframework.org/schema/jdbc/spring-jdbc.xsd">;
- <bean id="dataSource" class="org.apache.commons.dbcp.BasicDataSource"
- destroy-method="close">
- <property name="driverClassName" value="com.MySQL.jdbc.Driver"/>
- <property name="url" value="jdbc:MySQL://127.0.0.1:3306/WebMagic?characterEncoding=UTF-8"/>
- <property name="username" value="webmagic"/>
- <property name="password" value="webmagic"/>
- </bean>
- <beans profile="test">
- <bean id="dataSource" class="org.apache.commons.dbcp.BasicDataSource"
- destroy-method="close">
- <property name="driverClassName" value="org.h2.Driver"/>
- <property name="url" value="jdbc:h2:mem:WebMagic;DB_CLOSE_DELAY=-1"/>
- </bean>
- <!--Refer to https://GitHub.com/springside/springside4/wiki/H2-Database -->
- <jdbc:initialize-database data-source="dataSource" ignore-failures="ALL">
- <jdbc:script location="classpath:sql/h2/schema.sql" />
- <!--<jdbc:script location="classpath:data/h2/import-data.sql" encoding="UTF-8"/>-->
- </jdbc:initialize-database>
- </beans>
- <beans profile="standalone">
- <bean id="dataSource" class="org.apache.commons.dbcp.BasicDataSource"
- destroy-method="close">
- <property name="driverClassName" value="org.h2.Driver"/>
- <property name="url" value="jdbc:h2:file:~/.h2/WebMagic;AUTO_SERVER=TRUE"/>
- </bean>
- <!--Refer to https://GitHub.com/springside/springside4/wiki/H2-Database -->
- <jdbc:initialize-database data-source="dataSource" ignore-failures="ALL">
- <jdbc:script location="classpath:sql/h2/schema.sql" />
- <!--<jdbc:script location="classpath:data/h2/import-data.sql" encoding="UTF-8"/>-->
- </jdbc:initialize-database>
- </beans>
- </beans>
设置 Profile 有不同的方式.
在 JUnit 里面, 使用注解 @ActiveProfile 即可.
- @RunWith(SpringJUnit4Cla * **unner.class)@ContextConfiguration(locations = {
- "classpath:/config/spring/applicationContext.xml"
- }) br / >@ActiveProfiles("test")@Transactional public abstract class AbstractTest {}
Web 项目则是在 Web.xml 里设置: mailto:br/>@ActiveProfiles(
- <init-param>
- <param-name>
- spring.profiles.active
- </param-name>
- <param-value>
- product
- </param-value>
- </init-param>
总结:
mailto:br/>@ActiveProfiles(
如此配置, 就可以达到在不同的环境使用不同 bean 的目的!
来源: http://blog.51cto.com/13932491/2177275