多数据源的使用

一、多数据源配置

publicKey、password生成(即加密):

(1)cmd打开druid-1.0.18.jar所在文件目录。
(2)执行命令:java -cp druid-1.0.18.jar com.alibaba.druid.filter.config.ConfigTools 数据库密码
(3)将得到的publickey、password复制过来即可。

解密:

执行com.alibaba.druid.filter.config.ConfigTools.decrypt(publicKey, password)得到密码明文

1.db.properties文件配置,有几个数据源就配置几个driver、url、username、password、publicKey,同时还有一个decrypt,指的是数据库密码是否需要解密,示例如下:

#datasource1
jdbc.driver=com.mysql.jdbc.Driver
jdbc.url=jdbc:mysql://183.129.148.83:3307/manageplat?useUnicode=true&characterEncoding=utf-8
jdbc.username=root
jdbc.password=CFIe1ASc5Kb1retmG068HgjTMPPrpgxLBzvQSBXES5EbA4NLmamb45NXPFSyuzP1ApFBQ1fjmWeKrTHwqpqXDw==
publicKey=MFwwDQYJKoZIhvcNAQEBBQADSwAwSAJBAJRxH4KqChe8kyA2HaEBlM/vOraezJQhw43Ya8WfCQhu6LHXfyWiZqHDMUsLSQaFeYVSWFyINePnuc5IVlil5mUCAwEAAQ==

#datasource2
#jdbc.driver2=oracle.jdbc.driver.OracleDriver
#jdbc.url2=jdbc:oracle:thin:@172.16.200.117:1521:ORCL
#jdbc.username2=manageplat
#jdbc.password2=eyhj9Gg+/9ETYwX2MhDgsH+5HGTd8mhFPZ11Wv9z3UixP+eBiS7Sex49V0KqsYosA09UgrfLNDRz7a5M9tIWwQ==
#publicKey2=MFwwDQYJKoZIhvcNAQEBBQADSwAwSAJBAJQ7ES+yG/PHawLgQWbjBOpQnrTaQPjtM/cu2FQUt9mKNgJtiHMKkkquFAD6h/ffHAGHznDMN//HPj83YOTfYnsCAwEAAQ==

#decrypt:Does the password need to be decrypted?true--need,else--don't need
decrypt=true

2.applicationContext-dao.xml文件配置,有几个数据源就配置几个DruidDataSource、SqlSessionFactoryBean、MapperScannerConfigurer,示例如下:

(1)DataSource,多个DataSource配置时一般只需将id、driverClassName、url、username、password修改即可。

<bean id="dataSource" class="com.alibaba.druid.pool.DruidDataSource" init-method="init" destroy-method="close">
    <property name="driverClassName" value="${jdbc.driver}" /> <property name="url" value="${jdbc.url}" />
    <property name="username" value="${jdbc.username}" />
    <property name="password" value="${jdbc.password}" />
    <!-- 配置初始化大小、最小、最大 -->
    <property name="initialSize" value="5" />
    <property name="minIdle" value="1" />
    <property name="maxActive" value="20" />
    <!-- 配置获取连接等待超时的时间 -->
    <property name="maxWait" value="60000" />
    <!-- 配置间隔多久才进行一次检测,检测需要关闭的空闲连接,单位是毫秒 -->
    <property name="timeBetweenEvictionRunsMillis" value="60000" />
    <!-- 配置一个连接在池中最小生存的时间,单位是毫秒 -->
    <property name="minEvictableIdleTimeMillis" value="300000" />
    <property name="validationQuery" value="#{'#{jdbc.driver}'=='com.mysql.jdbc.Driver'?'SELECT 1':'SELECT 1 FROM DUAL'}" />
    <property name="testWhileIdle" value="true" />
    <property name="testOnBorrow" value="false" />
    <property name="testOnReturn" value="false" />
    <!-- 打开PSCache,并且指定每个连接上PSCache的大小 -->
    <property name="poolPreparedStatements" value="true" />
    <property name="maxPoolPreparedStatementPerConnectionSize" value="20" />
    <property name="filters" value="config,stat" />
    <property name="connectionProperties" value="config.decrypt=${decrypt};config.decrypt.key=${publicKey}" />
</bean>

<bean id="dataSource2" class="com.alibaba.druid.pool.DruidDataSource" init-method="init" destroy-method="close">
    <property name="driverClassName" value="${jdbc.driver2}" /> <property name="url" value="${jdbc.url2}" />
    <property name="username" value="${jdbc.username2}" />
    <property name="password" value="${jdbc.password2}" />
    <!-- 配置初始化大小、最小、最大 -->
    <property name="initialSize" value="5" />
    <property name="minIdle" value="1" />
    <property name="maxActive" value="20" />
    <!-- 配置获取连接等待超时的时间 -->
    <property name="maxWait" value="60000" />
    <!-- 配置间隔多久才进行一次检测,检测需要关闭的空闲连接,单位是毫秒 -->
    <property name="timeBetweenEvictionRunsMillis" value="60000" />
    <!-- 配置一个连接在池中最小生存的时间,单位是毫秒 -->
    <property name="minEvictableIdleTimeMillis" value="300000" />
    <property name="validationQuery" value="#{'#{jdbc.driver}'=='com.mysql.jdbc.Driver'?'SELECT 1':'SELECT 1 FROM DUAL'}" />
    <property name="testWhileIdle" value="true" />
    <property name="testOnBorrow" value="false" />
    <property name="testOnReturn" value="false" />
    <!-- 打开PSCache,并且指定每个连接上PSCache的大小 -->
    <property name="poolPreparedStatements" value="true" />
    <property name="maxPoolPreparedStatementPerConnectionSize" value="20" />
    <property name="filters" value="config,stat" />
    <property name="connectionProperties" value="config.decrypt=${decrypt};config.decrypt.key=${publicKey2}" />
</bean>

(2)SqlSessionFactory,多个SqlSessionFactory配置时只需将id、dataSource修改即可。

<bean id="sqlSessionFactory" class="org.mybatis.spring.SqlSessionFactoryBean">
    <property name="dataSource" ref="dataSource"></property>
    <property name="configLocation" value="classpath:config/mybatis/SqlMapConfig.xml" />
    <property name="databaseIdProvider" ref="databaseIdProvider"/>
</bean>

<bean id="sqlSessionFactory2" class="org.mybatis.spring.SqlSessionFactoryBean">
    <property name="dataSource" ref="dataSource2"></property>
    <property name="configLocation" value="classpath:config/mybatis/SqlMapConfig.xml" />
    <property name="databaseIdProvider" ref="databaseIdProvider"/>
</bean>

(3)MapperScannerConfigurer,多个MapperScannerConfigurer配置时只需将basePackage、sqlSessionFactoryBeanName修改即可,其中basePackage的value对应逆向工程生成文件时generatorConfig.xml中配置的后两个targetPackage目录,关于此处详情可见本页最后。

<bean class="org.mybatis.spring.mapper.MapperScannerConfigurer">
    <!-- 配置扫描包的路径,如果要扫描多个包,中间使用半角逗号分隔,要求mapper.xml和mapper.java同名且在同一个目录-->
    <property name="basePackage" value="com.cnnct.mapper"/>
    <!-- 使用sqlSessionFactoryBeanName -->
    <property name="sqlSessionFactoryBeanName" value="sqlSessionFactory"/>
</bean>

<bean class="org.mybatis.spring.mapper.MapperScannerConfigurer">
    <!-- 配置扫描包的路径,如果要扫描多个包,中间使用半角逗号分隔,要求mapper.xml和mapper.java同名且在同一个目录-->
    <property name="basePackage" value="com.cnnct.mapperoracle"/>
    <!-- 使用sqlSessionFactoryBeanName -->
    <property name="sqlSessionFactoryBeanName" value="sqlSessionFactory2"/>
</bean>

3.如果需要用到事务,还需配置applicationContext-transation.xml文件,有几个数据源就配置几个DataSourceTransactionManager、txAdvice、aop:config,示例如下:

(1)DataSourceTransactionManager

<bean id="transactionManager" class="org.springframework.jdbc.datasource.DataSourceTransactionManager">
    property name="dataSource" ref="dataSource"></property>
</bean>

<bean id="transactionManager2" class="org.springframework.jdbc.datasource.DataSourceTransactionManager">
    <property name="dataSource" ref="dataSource2"></property>
</bean>

(2)txAdvice

<tx:advice id="txAdvice" transaction-manager="transactionManager">
    <tx:attributes>
        <tx:method name="*" propagation="REQUIRED"/>
        <tx:method name="notran*" propagation="NOT_SUPPORTED" />
    </tx:attributes>
</tx:advice>

<tx:advice id="txAdvice2" transaction-manager="transactionManager2">
    <tx:attributes>
        <tx:method name="*" propagation="REQUIRED"/>
        <tx:method name="notran*" propagation="NOT_SUPPORTED" />
    </tx:attributes>
</tx:advice>

(3)aop:config

<aop:config expose-proxy="true">
    <!-- 切入包下面的所有类的所有方法 不管返回值是什么,不管输入参数是什么 -->
    <aop:advisor advice-ref="txAdvice" pointcut="execution(* com.cnnct.._ServImpl.*(..))"/>
</aop:config>

<aop:config expose-proxy="true">
    <!-- 切入包下面的所有类的所有方法 不管返回值是什么,不管输入参数是什么 -->
    <aop:advisor advice-ref="txAdvice2" pointcut="execution(* com.cnnct.._ServImpl.*(..))"/>
</aop:config>

二、多数据源逆向工程

1.generatorConfig.xml文件配置

注:

  • 每次使用逆向工程为一个数据源生成文件后,就修改一下driverClass、connectionURL、userId、password、publicKey以及3个targetPackage的值,还有<table>的tableName,配置上需要逆向工程生成文件的表,然后再执行逆向工程GeneratorSqlmap.java。

  • 每次运行GeneratorSqlmap.java生成文件时,会自动删除已存在的基础实体类和基础mapper的同名文件,因此使用前一定注意是否这三个文件有做过个性化修改。

  • 因此,鉴于前一事项,建议基础实体类和基础的mapper尽量不要去修改,若要修改或增加功能,在custom中进行处理。

  • 以上提到的三个基础文件及custom为别为:

/src/com/cnnct/po/表名.java,对应的custom文件:/src/com/cnnct/po/custom/表名Cust.java

/src/com/cnnct/mapper/表名Mapper.java,对应的custom文件:/src/com/cnnct/mapper/custom/表名CustMapper.java

/src/com/cnnct/mapper/表名Mapper.xml,对应的custom文件:/src/com/cnnct/mapper/custom/表名CustMapper.xml

<generatorConfiguration>
    <properties resource="config/parameter/db.properties"/>
    <context id="testTables" targetRuntime="MyBatis3" defaultModelType="flat">
        <!-- 生成PO类时序列化 -->
        <plugin type="org.mybatis.generator.plugins.SerializablePlugin" />
        <commentGenerator>
            <!-- 是否去除自动生成的注释 true:是 : false:否 -->
            <property name="suppressAllComments" value="true" />
        </commentGenerator>
        <!--数据库连接的信息:驱动类、连接地址、用户名、密码 -->
        <jdbcConnection driverClass="${jdbc.driver}"
            connectionURL="${jdbc.url}" userId="${jdbc.username}"
            password="${jdbc.password} publicKey="${publicKey}">
        </jdbcConnection>

        <!-- 默认false,把JDBC DECIMAL 和 NUMERIC 类型解析为 Integer,为 true时把JDBC DECIMAL 和
            NUMERIC 类型解析为java.math.BigDecimal -->
        <javaTypeResolver>
            <property name="forceBigDecimals" value="false" />
        </javaTypeResolver>

        <!-- targetProject:生成PO类的位置 -->
        <javaModelGenerator targetPackage="com.cnnct.po"
            targetProject=".\src">
            <!-- enableSubPackages:是否让schema作为包的后缀 -->
            <property name="enableSubPackages" value="false" />
            <!-- 从数据库返回的值被清理前后的空格 -->
            <property name="trimStrings" value="true" />
        </javaModelGenerator>
        <!-- targetProject:mapper映射文件生成的位置 -->
        <sqlMapGenerator targetPackage="com.cnnct.mapper"
            targetProject=".\src">
            <!-- enableSubPackages:是否让schema作为包的后缀 -->
            <property name="enableSubPackages" value="false" />
        </sqlMapGenerator>
        <!-- targetPackage:mapper接口生成的位置 -->
        <javaClientGenerator type="XMLMAPPER"
            targetPackage="com.cnnct.mapper"
            targetProject=".\src">
            <!-- enableSubPackages:是否让schema作为包的后缀 -->
            <property name="enableSubPackages" value="false" />
        </javaClientGenerator>

         <!-- 表配置,如果数据库为oracle,那么,还需要加上schema属性,值为oracle用户名 -->
         <table tableName="bs_city" enableCountByExample="false" enableUpdateByExample="false" enableDeleteByExample="false" enableSelectByExample="false" selectByExampleQueryId="false"></table>
         <table tableName="bs_city" schema="manageplat" enableCountByExample="false" enableUpdateByExample="false" enableDeleteByExample="false" enableSelectByExample="false" selectByExampleQueryId="false"></table>
         <!-- 自定义数据库中的字段映射的实体类属性类型 -->
         <table tableName="sys_action_log" enableCountByExample="false" enableUpdateByExample="false" enableDeleteByExample="false" enableSelectByExample="false" selectByExampleQueryId="false">
             <columnOverride column="message" javaType="java.lang.String" jdbcType="VARCHAR"/>
             <columnOverride column="in_data" javaType="java.lang.String" jdbcType="VARCHAR"/>
             <columnOverride column="out_data" javaType="java.lang.String" jdbcType="VARCHAR"/>
         </table>
    </context>
</generatorConfiguration>

2.关于generatorConfig.xml文件中的三个targetPackage目录配置说明

初始单数据源或多数据源的第一个数据源时,三个targetPackage分别默认为:com.cnnct.po、com.cnnct.mapper、com.cnnct.mapper。
如果配置多个数据源或不想用这3个默认目录,修改规则为:在此3个目录的基础上补上一个后缀,后两个目录必须相同。
如:com.cnnct.po2、com.cnnct.mapper2、com.cnnct.mapper2
或 com.cnnct.pooracle、com.cnnct.mapperoracle、com.cnnct.mapperoracle等。
而这里的后两个目录(相同,即同一个目录),对应applicationContext-dao.xml文件中basePackage,通过数据源一一对应。

注:如果使用的不是3个默认目录,那么,注入基础Mapper(非custom中的)时,需要使用别名,别名在基础Mapper中有。

示例:

基础Mapper

package com.cnnct.mapper;

import org.springframework.stereotype.Component;

import com.cnnct.po.SysRole;

@Component("sysRoleMapperOracle")
public interface SysRoleMapper {
    int deleteByPrimaryKey(Long roleId);

    int insert(SysRole record);

    int insertSelective(SysRole record);

    SysRole selectByPrimaryKey(Long roleId);

    int updateByPrimaryKeySelective(SysRole record);

    int updateByPrimaryKey(SysRole record);
}

注入代码,此处为sysRoleMapperOracle对应基础Mapper中的别名,而不能随意起名

@Autowired
private SysRoleMapper sysRoleMapperOracle;

3.由于oralce中number类型长度的变化,导致生成的实体类的类型变化问题

可以通过修改generatorConfig.xml中的如下配置固定类型:

<!-- 默认false,根据数据库中字段类型长度把JDBC DECIMAL 和 NUMERIC 类型解析为对应的类型;为 true时把JDBC DECIMAL 和
    NUMERIC 类型解析为java.math.BigDecimal -->
<javaTypeResolver>
    <property name="forceBigDecimals" value="false" />
</javaTypeResolver>

results matching ""

    No results matching ""