zoukankan      html  css  js  c++  java
  • Spring + mybatis 主从数据库分离读写的几种方式(三)

    转载:

    如何使用spring配合mybatis配置多个数据源并应用? (多DataSource)

     

      使用多数据源的场景应该是很多的,如操作同一台服务器上不同的数据库,或者多地机器上的相同或不相同数据库。

      虽然涉及到不同数据库时,我们也许可以通过跨库操作的方式,如 other.user 使用同一数据源来操作数据库,但是,这样明显使得应用很难扩展,单数据库将无法拆离。使用多数据源操作则可以解决这个问题。

      在spring中怎样使用多数据源?本文通过实践方式,让我配置多数据源有个参考。(不得不说,java中很大的一个难点就在于配置环境)

      从入口处更改,web.xml中添加引用spring配置文件:

    <?xml version="1.0" encoding="UTF-8"?>
    <web-app xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns="http://java.sun.com/xml/ns/javaee" xsi:schemaLocation="http://java.sun.com/xml/ns/javaee http://java.sun.com/xml/ns/javaee/web-app_3_0.xsd" version="3.0">
      <display-name>c</display-name>
      <filter>
        <filter-name>characterEncodingFilter</filter-name>
        <filter-class>org.springframework.web.filter.CharacterEncodingFilter</filter-class>
        <init-param>
          <param-name>encoding</param-name>
          <param-value>UTF-8</param-value>
        </init-param>
        <init-param>
          <param-name>forceEncoding</param-name>
          <param-value>true</param-value>
        </init-param>
      </filter>
      <filter-mapping>
        <filter-name>characterEncodingFilter</filter-name>
        <url-pattern>/*</url-pattern>
      </filter-mapping>
      <servlet>
        <servlet-name>dispatcherServlet</servlet-name>
        <servlet-class>org.springframework.web.servlet.DispatcherServlet</servlet-class>
        <init-param>
          <param-name>contextConfigLocation</param-name>
          <param-value>classpath:applicationContext.xml</param-value>
        </init-param>
        <load-on-startup>1</load-on-startup>
      </servlet>
       <!-- URL重写 -->
        <filter>
            <filter-name>UrlRewriteFilter</filter-name>
            <filter-class>org.tuckey.web.filters.urlrewrite.UrlRewriteFilter</filter-class>
        </filter>
        <filter-mapping>
            <filter-name>UrlRewriteFilter</filter-name>
            <url-pattern>/*</url-pattern>
            <dispatcher>REQUEST</dispatcher>
            <dispatcher>FORWARD</dispatcher>
        </filter-mapping>
        
      <servlet-mapping>
        <servlet-name>dispatcherServlet</servlet-name>
        <url-pattern>/api/*</url-pattern>
      </servlet-mapping>
      
      <display-name>c</display-name>
      <welcome-file-list>
        <welcome-file>index.html</welcome-file>
      </welcome-file-list>
        
      <filter> 
      <filter-name>JAMonFilter</filter-name>  
      <filter-class>com.xx.core.web.filter.PageMonFilter</filter-class> 
      <init-param>
      <param-name>flag</param-name>
      <param-value>true</param-value>
      </init-param>
      </filter> 
      <filter-mapping> 
      <filter-name>JAMonFilter</filter-name> 
      <url-pattern>/*</url-pattern> 
      </filter-mapping>
      <servlet>
       <servlet-name>exceptions</servlet-name> 
       <jsp-file>/jamon/exceptions.jsp</jsp-file> 
       </servlet> 
       <servlet> 
    </web-app>

    2. 在application.xml中添加多数据源配置:

    <?xml version="1.0" encoding="UTF-8"?>
    <beans xmlns="http://www.springframework.org/schema/beans"
        xmlns:context="http://www.springframework.org/schema/context" xmlns:tx="http://www.springframework.org/schema/tx"
        xmlns:aop="http://www.springframework.org/schema/aop" xmlns:mvc="http://www.springframework.org/schema/mvc"
        xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:p="http://www.springframework.org/schema/p"
        xmlns:mongo="http://www.springframework.org/schema/data/mongo"
        xsi:schemaLocation="
            http://www.springframework.org/schema/beans     
            http://www.springframework.org/schema/beans/spring-beans-4.0.xsd
            http://www.springframework.org/schema/context
            http://www.springframework.org/schema/context/spring-context-4.0.xsd
            http://www.springframework.org/schema/tx
            http://www.springframework.org/schema/tx/spring-tx-4.0.xsd
            http://www.springframework.org/schema/aop
            http://www.springframework.org/schema/aop/spring-aop-4.0.xsd
            http://www.springframework.org/schema/mvc
            http://www.springframework.org/schema/mvc/spring-mvc-4.0.xsd
            http://www.springframework.org/schema/data/mongo
            http://www.springframework.org/schema/data/mongo/spring-mongo-1.5.xsd">
    
        <bean class="com.xx.c.common.utils.SpringContextsUtil" />
        <bean id="dataSource" class="com.alibaba.druid.pool.DruidDataSource"
            destroy-method="close">
            <property name="url" value="${jdbc.url}" />
            <property name="driverClassName" value="${jdbc.driver}" />
            <property name="maxActive" value="${pool.maxPoolSize}" />
            <property name="username" value="${jdbc.username}" />
            <property name="password" value="${jdbc.password}" />
            <!-- 超过时间限制是否回收 -->
            <property name="removeAbandoned" value="true" />
            <!-- 超时时间;单位为秒。180秒=3分钟 -->
            <property name="removeAbandonedTimeout" value="${pool.removeAbandonedTimeout}" />
            <!-- 配置获取连接等待超时的时间 -->
            <property name="maxWait" value="${pool.maxWait}" />
            <!-- 配置间隔多久才进行一次检测,检测需要关闭的空闲连接,单位是毫秒 -->
            <property name="timeBetweenEvictionRunsMillis" value="${pool.timeBetweenEvictionRunsMillis}" />
            <!-- 配置一个连接在池中最小生存的时间,单位是毫秒 -->
            <property name="minEvictableIdleTimeMillis" value="${pool.minEvictableIdleTimeMillis}" />
            <property name="validationQuery" value="${pool.validationQuery} " />
            <property name="testWhileIdle" value="true" />
            <property name="testOnBorrow" value="false" />
            <property name="testOnReturn" value="false" />
        </bean>
        <bean id="dataSource_c" class="com.alibaba.druid.pool.DruidDataSource"
            destroy-method="close">
            <property name="url" value="${jdbc2.url}" />
            <property name="driverClassName" value="${jdbc2.driver}" />
            <property name="maxActive" value="${pool2.maxPoolSize}" />
            <property name="username" value="${jdbc2.username}" />
            <property name="password" value="${jdbc2.password}" />
            <property name="removeAbandoned" value="true" />
            <property name="removeAbandonedTimeout" value="${pool2.removeAbandonedTimeout}" />
            <property name="maxWait" value="${pool2.maxWait}" />
            <property name="timeBetweenEvictionRunsMillis" value="${pool2.timeBetweenEvictionRunsMillis}" />
            <property name="minEvictableIdleTimeMillis" value="${pool2.minEvictableIdleTimeMillis}" />
            <property name="validationQuery" value="${pool2.validationQuery} " />
            <property name="testWhileIdle" value="true" />
            <property name="testOnBorrow" value="false" />
            <property name="testOnReturn" value="false" />
        </bean>
        <context:component-scan base-package="com.xx.c">
            <context:exclude-filter type="annotation"
                expression="org.springframework.stereotype.Controller" />
        </context:component-scan>
        <context:component-scan base-package="com.xx.c.pojo.config" />
        <bean class="com.xx.framework.web.v1_0_0.ServerController" />
    
        <!-- spring的属性加载器,加载properties文件中的属性 -->
        <bean class="com.xx.zkc.property.PropertyPlaceholderConfigurer">
            <property name="systemPropertiesModeName" value="SYSTEM_PROPERTIES_MODE_OVERRIDE" />
            <property name="ignoreResourceNotFound" value="true" />
            <property name="locations">
                <list>
                    <value>classpath*:/spring/conf.properties</value>
                </list>
            </property>
        </bean>
        
        <bean id="sqlSessionFactory" class="org.mybatis.spring.SqlSessionFactoryBean">
            <property name="dataSource" ref="dataSource" />
            <property name="configLocation" value="classpath:mybatis-config.xml" />
        </bean>
        <bean id="sqlSessionFactory_c" class="org.mybatis.spring.SqlSessionFactoryBean">
            <property name="dataSource" ref="dataSource_c" />
            <property name="configLocation" value="classpath:mybatis-config.xml" />
        </bean>
        <bean id="sqlSession" class="org.mybatis.spring.SqlSessionTemplate"
            scope="prototype">
            <constructor-arg index="0" ref="sqlSessionFactory" />
        </bean>
        <bean id="sqlSession_c" class="org.mybatis.spring.SqlSessionTemplate"
            scope="prototype">
            <constructor-arg index="0" ref="sqlSessionFactory_c" />
        </bean>
    
    
        <mongo:mongo id="mongo" replica-set="${mongodb.url}">
            <mongo:options connections-per-host="${mongo.connections.per.host}"
                threads-allowed-to-block-for-connection-multiplier="${mongo.threads.allowed.to.block.for.connection.multiplier}"
                connect-timeout="${mongo.connect.timeout}" max-wait-time="${mongo.max.wait.time}"
                auto-connect-retry="${mongo.auto.connect.retry}" socket-keep-alive="${mongo.socket.keep.alive}"
                socket-timeout="${mongo.socket.timeout}" slave-ok="${mongo.slave.ok}"
                write-number="${mongo.write.number}" write-timeout="${mongo.write.timeout}"
                write-fsync="${mongo.write.fsync}" />
        </mongo:mongo>
        <bean id="mappingContext"
            class="org.springframework.data.mongodb.core.mapping.MongoMappingContext" />
        <bean id="defaultMongoTypeMapper"
            class="org.springframework.data.mongodb.core.convert.DefaultMongoTypeMapper">
            <constructor-arg name="typeKey">
                <null />
            </constructor-arg>
        </bean>
        <bean id="mongoDbFactory"
            class="org.springframework.data.mongodb.core.SimpleMongoDbFactory">
            <constructor-arg ref="mongo" />
            <constructor-arg name="databaseName" value="${mongodb.databaseName}" />
        </bean>
    
        <bean id="mappingMongoConverter"
            class="org.springframework.data.mongodb.core.convert.MappingMongoConverter">
            <constructor-arg name="mappingContext" ref="mappingContext" />
            <property name="typeMapper" ref="defaultMongoTypeMapper" />
            <constructor-arg name="mongoDbFactory" ref="mongoDbFactory" />
        </bean>
    
        <bean id="mongodbReadPreference" class="com.mongodb.ReadPreference"
            factory-method="secondaryPreferred" />
        <bean id="mongoTemplate" class="org.springframework.data.mongodb.core.MongoTemplate">
            <property name="readPreference" ref="mongodbReadPreference" />
            <constructor-arg name="mongoConverter" ref="mappingMongoConverter" />
            <constructor-arg name="mongoDbFactory" ref="mongoDbFactory" />
        </bean>
    
        <!-- 事务 控制 begin -->
        <bean name="transactionManager"
            class="org.springframework.jdbc.datasource.DataSourceTransactionManager">
            <property name="dataSource" ref="dataSource"></property>
        </bean>
        <tx:annotation-driven transaction-manager="transactionManager" />
        <!-- 事务 控制 end -->
    
        <!-- action begin -->
        <bean name='requestMappingHandlerMapping'
            class='com.xx.core.web.spring.annotation.PackageURLRequestMappingHandlerMapping'>
            <property name='packageBase' value='com.xx.c.action'></property>
            <property name="interceptors">
                <list>
                    <bean class="com.xx.core.web.spring.interceptor.SessionInterceptor">
                        <property name="on" value="${system.check.permission}" />
                        <property name="sessionTimeout" value="${system.timeout}" />
                        <property name="userSessionDao" ref="userSessionDao" />
                        <property name="systemDao" ref="systemDao" />
                    </bean>
                </list>
            </property>
        </bean>
    
        <!-- dao -->
        <import resource="dao.xml" />
    
        <!-- service -->
        <import resource="service.xml" />
    
        <!-- activemq -->
        <import resource="applicationContext-activemq.xml" />
    
        <!-- redis -->
        <import resource="applicationContext-redis.xml" />
    
        <!-- dubbo -->
        <import resource="applicationContext-dubbo.xml" />
        <import resource="applicationContext-dubbo-consumer.xml" />
    
        <import resource="classpath:spring/xx-c-kafka-consumer.xml" />
        
        <import resource="applicationContext-rabbitmq-producer.xml"/>
        
        <import resource="applicationContext-rabbitmq-consumer.xml"/>
    
        <bean
            class="org.springframework.web.servlet.mvc.method.annotation.RequestMappingHandlerAdapter">
            <property name="messageConverters">
                <list>
                    <bean
                        class="com.xx.core.web.spring.convert.JSONHttpMessageConverter">
                    </bean>
                    <bean
                        class="org.springframework.http.converter.StringHttpMessageConverter">
                    </bean>
                    <bean
                        class="org.springframework.http.converter.ByteArrayHttpMessageConverter">
                    </bean>
                    <bean
                        class="org.springframework.http.converter.xml.SourceHttpMessageConverter">
                    </bean>
                    <bean
                        class="org.springframework.http.converter.support.AllEncompassingFormHttpMessageConverter">
                    </bean>
                </list>
            </property>
            <property name="customArgumentResolvers">
                <list>
                    <bean class="com.xx.core.web.spring.bind.TIDArgumentResolver" />
                    <bean
                        class="com.xx.core.web.spring.bind.RequestAttributeArgumentResolver" />
                    <bean class="com.xx.core.web.spring.bind.ClientIPArgumentResolver" />
                    <bean
                        class="com.xx.core.web.spring.bind.SessionUserIdArgumentResolver" />
                </list>
            </property>
        </bean>
    
        <bean id="dealException" class="com.xx.core.web.spring.interceptor.ExceptionAop"></bean>
        <aop:config>
            <!-- 对异常的集中处理 -->
            <aop:aspect id="exceptionAop" ref="dealException">
                <aop:pointcut id="exceptionPointCut"
                    expression="execution(* com.xx.c.action.*.*.*(..))" />
                <aop:around pointcut-ref="exceptionPointCut" method="deal" />
            </aop:aspect>
        </aop:config>
    
        <bean
            class="org.springframework.aop.framework.autoproxy.BeanNameAutoProxyCreator">
            <property name="beanNames">
                <list>
                    <value>systemDictDao</value>
                    <value>userDao</value>
                    <value>infoDao</value>
                </list>
            </property>
            <property name="interceptorNames">
                <list>
                    <value>jamonInterceptor</value>
                </list>
            </property>
        </bean>
        <bean id="jamonInterceptor"
            class="org.springframework.aop.interceptor.JamonPerformanceMonitorInterceptor"></bean>
         <bean id="multipartResolver"
            class="org.springframework.web.multipart.commons.CommonsMultipartResolver"
            p:defaultEncoding="utf-8" p:maxUploadSize="104857600" />
        <context:component-scan base-package="com.xx.c.action"
            name-generator="com.xx.core.web.spring.annotation.FullPackageBeanNameGenerator" /> 
        <!-- action end -->
        <!-- Spring托管线程池 -->
        <bean id="threadPoolTaskExecutor"
            class="org.springframework.scheduling.concurrent.ThreadPoolTaskExecutor">
            <!-- 线程池活跃的线程数 -->
            <property name="corePoolSize" value="50" />
            <!-- 线程池最大活跃的线程数 -->
            <property name="maxPoolSize" value="75" />
            <!-- 队列的最大容量 <property name ="queueCapacity" value ="2000" /> -->
            <!-- <property name="WaitForTasksToCompleteOnShutdown" value="true" /> -->
        </bean>
         
        <bean id="mapper" class="org.dozer.spring.DozerBeanMapperFactoryBean">
           <property name="mappingFiles">
                <list>        
                    <value>classpath:/dozerBeanMapping.xml</value>
                    <value>classpath:/dozerBeanMapping2.xml</value>
               </list>
           </property>
        </bean>    
        
    </beans>

    3. 在dao.xml中,添加对数据源的引用:

    <?xml version="1.0" encoding="UTF-8"?>
    <beans xmlns="http://www.springframework.org/schema/beans" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
        xsi:schemaLocation="
            http://www.springframework.org/schema/beans     
            http://www.springframework.org/schema/beans/spring-beans-4.0.xsd">
        <!-- import this -->
        <bean id="userDao" class="com.xx.c.dao.user.UserDaoImpl">
            <property name="sqlSession" ref="sqlSession" />
            <property name="mongoTemplate" ref ="mongoTemplate" />
        </bean>
        
        <bean id="infoDao" class="com.xx.c.dao.content.ConInfoDaoImpl">
            <property name="sqlSession" ref="sqlSession_c" />
        </bean>
    </beans>

    4. 在具体的sql当中实现数据操作:

    <?xml version="1.0" encoding="UTF-8"?>
    <!DOCTYPE mapper
      PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN"
      "http://mybatis.org/dtd/mybatis-3-mapper.dtd">
    
    <mapper namespace="com.xx.c.dao.user.UserDao">
        <resultMap id="userMap" type="User">
            <id column="user_id" property="userId" />
            <result column="username" property="userName" />
            <result column="sex" property="sex" />
        </resultMap>
        <resultMap id="userInfoMap" type="UserInfoBean">
            <id column="user_id" property="userId" />
            <result column="card_id" property="cardId" />
            <result column="username" property="phone" />
            <result column="id_card_address" property="idCardAddress" />
            <result column="reg_time" property="regTime" />
            <result column="logintime" property="logintime" />
            <result column="last_time" property="lastTime" />
            <result column="reg_ip" property="regIp" />
            <result column="up_ip" property="upIp" />
            <result column="last_ip" property="lastIp" />
            <result column="download_channel" property="downloadChannel" />
    
            <result column="guarantor1" property="guarantor1" />
            <result column="guarantor_phone1" property="guarantor_phone1" />
        </resultMap>
    
        <sql id="getUserCond">
            <where>
                <if test="userId != null">
                    and u.user_id = #{userId}
                </if>
                <if test="userName != null and userName != ''">
                    and u.username = #{userName}
                </if>
            </where>
        </sql>
        
        <select id="getUser" resultMap="userMap" parameterType="User">
            select u.* from users_info u
            <include refid="getUserCond" />
        </select>
    
        <insert id="addDebitCardBindChannel" parameterType="DebitCardBindChannelBean">
            insert into
            nzz (
            user_id,channel,
            card_no,request_id,status)
            values (
            #{userId},#{channel},#{cardNo},#{requestId},#{status})
        </insert>
    
        <update id="updateDebitCardBindChannel" parameterType="DebitCardBindChannelBean">
            update
            nzz
            set status=#{status}
            ,request_id=#{requestId}
            where
            user_id=#{userId} and card_no=#{cardNo}
            and channel=#{channel}
        </update>
    </mapper>

    5. 完善一下,使用别名,使sql写的时候更简短:

    <?xml version="1.0" encoding="UTF-8"?>
    <!DOCTYPE configuration
        PUBLIC "-//mybatis.org//DTD Config 3.0//EN"
        "http://mybatis.org/dtd/mybatis-3-config.dtd">
    
    <configuration>
    <settings>  
            <setting name="logPrefix" value="dao."/>  
    </settings> 
        <!-- 配置别名,以便在引用时简写 -->
        <typeAliases>
            <typeAlias alias="User" type="com.xx.c.pojo.user.User" />
            <typeAlias alias="CardBinBean" type="com.xx.c.pojo.user.CardBinBean"/>
            <typeAlias alias="UserCreditLogBean" type="com.xx.c.pojo.user.UserCreditLogBean"/>
            <typeAlias alias="InfoBean" type="com.xx.c.pojo.content.ContentInfo" /> 
        </typeAliases>
    
        <mappers>
            <mapper resource="com/xx/c/dao/impl/User.xml"/>
            <mapper resource="com/xx/c/dao/impl/Info.xml"/> 
        </mappers>
    
    </configuration>

    ----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------

    <bean id="readSqlSessionFactory" class="org.mybatis.spring.SqlSessionFactoryBean">
        <!-- 实例化sqlSessionFactory时需要使用上述配置好的数据源以及SQL映射文件 -->
        <property name="dataSource" ref="readDataSource"/>
        <property name="mapperLocations" value="classpath:mapper/read/*.xml"/>
    </bean>
     
    <bean id="writeSqlSessionFactory" class="org.mybatis.spring.SqlSessionFactoryBean">
        <!-- 实例化sqlSessionFactory时需要使用上述配置好的数据源以及SQL映射文件 -->
        <property name="dataSource" ref="writeDataSource"/>
        <property name="mapperLocations" value="classpath:mapper/write/*.xml"/>
    </bean>

    通过MyBatis配置文件创建读写分离两个DataSource,每个SqlSessionFactoryBean对象的mapperLocations属性制定两个读写数据源的配置文件。将所有读的操作配置在读文件中,所有写的操作配置在写文件中

    缺点:不够灵活、不易扩展

    ----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------

    MyBatis多数据源配置(读写分离) 

  • 相关阅读:
    oracle 删除表中重复数据留一条
    C# 特性
    oracle 常用简单命令语句
    2017年学习计划
    java web开发基础学习
    Java Axis2支持json
    java基础教程
    axis2 发布webservice
    孤荷凌寒自学python第103天认识区块链017
    孤荷凌寒自学python第102天认识区块链016
  • 原文地址:https://www.cnblogs.com/supperlhg/p/9238363.html
Copyright © 2011-2022 走看看