• spring+springmvc+mybatis+oracle+atomikos+jta实现多数据源事务管理


    ---恢复内容开始---

           在做项目过程中,遇到了需要一个项目中访问两个数据库的情况,发现使用常规的spring管理事务,导致事务不能正常回滚,因此,采用了jta+atomikos的分布式数据源方式对事务进行管理。在此做下记录,以便日后参考,文中用词不当之处,敬请谅解!

    配置文件:

    1:web.xml

    <?xml version="1.0" encoding="UTF-8"?>
    <web-app version="3.0" xmlns="http://java.sun.com/xml/ns/javaee" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
             xsi:schemaLocation="http://java.sun.com/xml/ns/javaee http://java.sun.com/xml/ns/javaee/web-app_3_0.xsd">
    
       <!-- 加载Spring配置文件 -->
        <context-param>
            <param-name>contextConfigLocation</param-name>
            <param-value>classpath:spring/spring.xml
            </param-value>
        </context-param>
        
    
    
        <!-- 字符集 过滤器 -->
        <filter>
            <filter-name>encodingFilter</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>
        </filter>
        <filter-mapping>
            <filter-name>encodingFilter</filter-name>
            <url-pattern>/*</url-pattern>
        </filter-mapping>
    
        <!-- Spring监听器 -->
        <listener>
            <description>Spring监听器</description>
            <listener-class>org.springframework.web.context.ContextLoaderListener</listener-class>
        </listener>
        <!-- 防止Spring内存溢出监听器 -->
        <listener>
            <listener-class>org.springframework.web.util.IntrospectorCleanupListener</listener-class>
        </listener>
    
    
    
        <!-- Spring MVC -->
        <servlet>
            <servlet-name>SpringMVC</servlet-name>
            <servlet-class>org.springframework.web.servlet.DispatcherServlet</servlet-class>
            <init-param>
                <description>SpringMVC</description>
                <param-name>contextConfigLocation</param-name>
                <param-value>classpath:spring/spring-mvc.xml</param-value>
            </init-param>
            <load-on-startup>1</load-on-startup>
        </servlet>
        <servlet-mapping>
            <servlet-name>SpringMVC</servlet-name>
            <url-pattern>*.do</url-pattern>
        </servlet-mapping>
    
        <!-- Session超时时间 -->
        <session-config>
            <session-timeout>15</session-timeout>
        </session-config>
    </web-app>

    2:pom.xml

    <properties>
            <project.build.sourceEncoding>UTF- 8</project.build.sourceEncoding>
            <spring.version>4.2.5.RELEASE</spring.version>
            <junit.version>4.12</junit.version>
            <druid.version>1.0.18</druid.version>
            <fastjson.version>1.2.6</fastjson.version>
            <mybaitsplus.version>2.0.8</mybaitsplus.version>
            <mysql.version>5.1.38</mysql.version>
            <log4j.version>1.2.17</log4j.version>
            <slf4j.version>1.7.13</slf4j.version>
            <aspectjweaver.version>1.8.9</aspectjweaver.version>
            <fileupload.version>1.3.1</fileupload.version>
            <commons.version>2.4</commons.version>
            <jstl.version>1.2</jstl.version>
        </properties>
    
        <dependencies>
            <!-- JUnit -->
            <dependency> 
                <groupId>junit</groupId>
                <artifactId>junit</artifactId>
                <version>${junit.version}</version>
                <scope>test</scope>
            </dependency>
            <!-- spring quartz -->
            <dependency>
                <groupId>org.quartz-scheduler</groupId>
                <artifactId>quartz</artifactId>
                <version>2.2.1</version>
            </dependency>
    <!-- 添加Hibernate依赖 -->    
        <dependency>  
          <groupId>org.hibernate</groupId>  
          <artifactId>hibernate-core</artifactId>  
          <version>3.6.10.Final</version>  
        </dependency>  
            <!-- redis -->
            <dependency>
                <groupId>redis.clients</groupId>
                <artifactId>jedis</artifactId>
                <version>2.5.1</version>
            </dependency>
    
            <!-- json -->
            <dependency>
                <groupId>net.sf.json-lib</groupId>
                <artifactId>json-lib</artifactId>
                <version>2.4</version>
                <classifier>jdk15</classifier>
            </dependency>
            <dependency>
                <groupId>org.codehaus.jackson</groupId>
                <artifactId>jackson-core-asl</artifactId>
                <version>1.9.11</version>
            </dependency>
            <dependency>
                <groupId>org.codehaus.jackson</groupId>
                <artifactId>jackson-mapper-asl</artifactId>
                <version>1.9.11</version>
            </dependency>
            <dependency>
                <groupId>com.fasterxml.jackson.core</groupId>
                <artifactId>jackson-databind</artifactId>
                <version>2.2.2</version>
            </dependency>
    
            <!-- Spring -->
            <dependency>
                <groupId>org.springframework</groupId>
                <artifactId>spring-core</artifactId>
                <version>${spring.version}</version>
                <type>jar</type>
                <scope>compile</scope>
            </dependency>
            <dependency>
                <groupId>org.springframework</groupId>
                <artifactId>spring-context</artifactId>
                <version>${spring.version}</version>
                <type>jar</type>
                <scope>compile</scope>
            </dependency>
            <dependency>
                <groupId>org.springframework</groupId>
                <artifactId>spring-context-support</artifactId>
                <version>${spring.version}</version>
                <type>jar</type>
                <scope>compile</scope>
            </dependency>
            <dependency>
                <groupId>org.springframework</groupId>
                <artifactId>spring-tx</artifactId>
                <version>${spring.version}</version>
                <type>jar</type>
                <scope>compile</scope>
            </dependency>
            <dependency>
                <groupId>org.springframework</groupId>
                <artifactId>spring-aop</artifactId>
                <version>${spring.version}</version>
                <type>jar</type>
                <scope>compile</scope>
            </dependency>
            <dependency>
                <groupId>org.springframework</groupId>
                <artifactId>spring-beans</artifactId>
                <version>${spring.version}</version>
                <type>jar</type>
                <scope>compile</scope>
            </dependency>
            <dependency>
                <groupId>org.springframework</groupId>
                <artifactId>spring-jdbc</artifactId>
                <version>${spring.version}</version>
                <type>jar</type>
                <scope>compile</scope>
            </dependency>
            <dependency>
                <groupId>org.springframework.data</groupId>
                <artifactId>spring-data-redis</artifactId>
                <version>1.6.2.RELEASE</version>
            </dependency>
    
            <!-- Spring MVC -->
            <dependency>
                <groupId>org.springframework</groupId>
                <artifactId>spring-web</artifactId>
                <version>${spring.version}</version>
                <type>jar</type>
                <scope>compile</scope>
            </dependency>
            <dependency>
                <groupId>org.springframework</groupId>
                <artifactId>spring-webmvc</artifactId>
                <version>${spring.version}</version>
                <type>jar</type>
                <scope>compile</scope>
            </dependency>
    
            <!-- AOP -->
            <dependency>
                <groupId>org.aspectj</groupId>
                <artifactId>aspectjweaver</artifactId>
                <version>${aspectjweaver.version}</version>
            </dependency>
    
            <!-- spring mvc upload -->
            <dependency>
                <groupId>commons-fileupload</groupId>
                <artifactId>commons-fileupload</artifactId>
                <version>${fileupload.version}</version>
            </dependency>
            
            <dependency>
                <groupId>commons-io</groupId>
                <artifactId>commons-io</artifactId>
                <version>${commons.version}</version>
            </dependency>
    
            <dependency>
                <groupId>javax.servlet</groupId>
                <artifactId>jstl</artifactId>
                <version>${jstl.version}</version>
            </dependency>
    
            <!-- Mybatis-Plus -->
            <dependency>
                <groupId>com.baomidou</groupId>
                <artifactId>mybatis-plus</artifactId>
                <version>${mybaitsplus.version}</version>
            </dependency>
        <!-- httpclient -->
            <dependency>
                <groupId>org.apache.httpcomponents</groupId>
                <artifactId>httpclient</artifactId>
                <version>4.3</version>
            </dependency>
    
            <dependency>
                <groupId>commons-httpclient</groupId>
                <artifactId>commons-httpclient</artifactId>
                <version>3.1</version>
            </dependency>
            <dependency>
                <groupId>commons-configuration</groupId>
                <artifactId>commons-configuration</artifactId>
                <version>1.6</version>
            </dependency>
            <dependency>
                <groupId>org.apache.httpcomponents</groupId>
                <artifactId>httpcore</artifactId>
                <version>4.3</version>
            </dependency>
            <!-- httpclient end -->
        <!-- oracle -->
        <dependency>
            <groupId>com.oracle</groupId>
            <artifactId>ojdbc6</artifactId>
            <version>11.2.0.1.0</version>
        </dependency>
            <!-- Druid -->
            <dependency>
                <groupId>com.alibaba</groupId>
                <artifactId>druid</artifactId>
                <version>${druid.version}</version>
            </dependency>
    
            <!-- FastJson -->
            <dependency>
                <groupId>com.alibaba</groupId>
                <artifactId>fastjson</artifactId>
                <version>${fastjson.version}</version>
            </dependency>
    
            <!-- Log -->
            <dependency>
                <groupId>log4j</groupId>
                <artifactId>log4j</artifactId>
                <version>${log4j.version}</version>
            </dependency>
            <dependency>
                <groupId>org.slf4j</groupId>
                <artifactId>slf4j-api</artifactId>
                <version>${slf4j.version}</version>
            </dependency>
            <dependency>
                <groupId>org.slf4j</groupId>
                <artifactId>slf4j-log4j12</artifactId>
                <version>${slf4j.version}</version>
            </dependency>
            <!-- 新增 -->
            <dependency>
                <groupId>javax.servlet</groupId>
                <artifactId>javax.servlet-api</artifactId>
                <version>3.1.0</version>
            </dependency>
    
            <dependency>
                <groupId>org.apache.poi</groupId>
                <artifactId>poi</artifactId>
                <version>3.9</version>
            </dependency>
    
            <dependency>
                <groupId>org.slf4j</groupId>
                <artifactId>slf4j-log4j12</artifactId>
                <version>1.7.5</version>
            </dependency>
    
            <dependency>
                <groupId>org.apache.commons</groupId>
                <artifactId>commons-lang3</artifactId>
                <version>3.4</version>
            </dependency>
            <dependency>
                 <groupId>commons-codec</groupId>
                 <artifactId>commons-codec</artifactId>
                 <version>1.10</version>
             </dependency>
    
            <dependency>
                <groupId>com.alibaba</groupId>
                <artifactId>fastjson</artifactId>
                <version>1.2.6</version>
            </dependency>
    
            <dependency>
                <groupId>com.fasterxml.jackson.core</groupId>
                <artifactId>jackson-databind</artifactId>
                <version>2.7.4</version>
            </dependency>
    
            
    
            <!-- 校验 -->
            <dependency>
                <groupId>org.hibernate</groupId>
                <artifactId>hibernate-validator</artifactId>
                <version>5.1.3.Final</version>
            </dependency>
    
            <dependency>
                <groupId>javax.validation</groupId>
                <artifactId>validation-api</artifactId>
                <version>1.1.0.Final</version>
            </dependency>
    
            <dependency>
                <groupId>org.jboss.logging</groupId>
                <artifactId>jboss-logging</artifactId>
                <version>3.1.1.GA</version>
    
            </dependency>
            
            <!-- shiro -->
            <dependency>
                <groupId>org.apache.shiro</groupId>
                <artifactId>shiro-core</artifactId>
                <version>1.2.2</version>
            </dependency>
    
            <dependency>
                <groupId>org.apache.shiro</groupId>
                <artifactId>shiro-web</artifactId>
                <version>1.2.2</version>
            </dependency>
    
            <dependency>
                <groupId>org.apache.shiro</groupId>
                <artifactId>shiro-ehcache</artifactId>
                <version>1.2.2</version>
            </dependency>
    
            <dependency>
                <groupId>org.apache.shiro</groupId>
                <artifactId>shiro-quartz</artifactId>
                <version>1.2.2</version>
                <exclusions>
                    <exclusion>
                        <artifactId>quartz</artifactId>
                        <groupId>org.opensymphony.quartz</groupId>
                    </exclusion>
                </exclusions>
            </dependency>
    
            <dependency>
                <groupId>org.apache.shiro</groupId>
                <artifactId>shiro-spring</artifactId>
                <version>1.2.2</version>
            </dependency>
            
            <!-- mapper生成需要依赖 -->
            <!-- 模板引擎 -->
            <dependency>
                <groupId>org.apache.velocity</groupId>
                <artifactId>velocity</artifactId>
                <version>1.7</version>
            </dependency>
            
            <!-- FastdfsClient -->
    
            <dependency>
                <groupId>org.csource</groupId>
                <artifactId>fastdfs-client-java</artifactId>
                <version>1.27-SNAPSHOT</version>
            </dependency>
         <!-- atomikos 多数据源事务管理 -->        
            <dependency>  
        <groupId>javax.transaction</groupId>  
        <artifactId>jta</artifactId>  
        <version>1.1</version>  
        </dependency>  
        <dependency>  
            <groupId>com.atomikos</groupId>  
            <artifactId>atomikos-util</artifactId>  
            <version>3.7.0</version>  
        </dependency>  
        <dependency>  
            <groupId>com.atomikos</groupId>  
            <artifactId>transactions</artifactId>  
            <version>3.7.0</version>  
        </dependency>  
        <dependency>  
            <groupId>com.atomikos</groupId>  
            <artifactId>transactions-jta</artifactId>  
            <version>3.7.0</version>  
        </dependency>  
        <dependency>  
            <groupId>com.atomikos</groupId>  
            <artifactId>transactions-jdbc</artifactId>  
            <version>3.7.0</version>  
        </dependency>  
        <dependency>  
            <groupId>com.atomikos</groupId>  
            <artifactId>transactions-api</artifactId>  
            <version>3.7.0</version>  
        </dependency>  
        <dependency>  
            <groupId>cglib</groupId>  
            <artifactId>cglib-nodep</artifactId>  
            <version>3.2.2</version>  
        </dependency> 
        
        <dependency>
            <groupId>com.atomikos</groupId>
            <artifactId>transactions-jdbc-deprecated</artifactId>
            <version>3.7.0</version>
        </dependency>
            
        </dependencies>
      <build>
        <finalName>dataPlat</finalName>
      </build>

    3:config.properties

     配置数据源属性

        A_jdbc_url=jdbc:oracle:thin:@localhost:1521:orcl
        A_jdbc_username=test_one
       A_jdbc_password=password
        B_jdbc_url=jdbc:oracle:thin:@localhost:1521:orcl
      B_jdbc_username=test_two
        B_jdbc_password=password

    4、在resources目录下添加jta.properties文件

      com.atomikos.icatch.service=com.atomikos.icatch.standalone.UserTransactionServiceFactory
      com.atomikos.icatch.console_file_name=tm.out
      com.atomikos.icatch.log_base_name=tmlog
      com.atomikos.icatch.tm_unique_name=com.atomikos.spring.jdbc.tm
      com.atomikos.icatch.console_log_level=INFO

    5、spring-mvc.xml

    <mvc:default-servlet-handler/>
    
        <!-- Controller包(自动注入) -->
        <context:component-scan base-package="com.zzxw.web.controller">
        </context:component-scan>
    
        <mvc:annotation-driven>
            <!-- 处理responseBody 里面日期类型 -->
            <mvc:message-converters>
                <bean
                    class="org.springframework.http.converter.json.MappingJackson2HttpMessageConverter">
                    <property name="objectMapper">
                        <bean class="com.fasterxml.jackson.databind.ObjectMapper">
                            <property name="dateFormat">
                                <bean class="java.text.SimpleDateFormat">
                                    <constructor-arg type="java.lang.String" value="yyyy-MM-dd HH:mm:ss" />
                                </bean>
                            </property>
                        </bean>
                    </property>
                </bean>
                <bean id="mappingJacksonHttpMessageConverter"  class="org.springframework.http.converter.json.MappingJackson2HttpMessageConverter" >
                    <property name="supportedMediaTypes">
                        <list>
                            <value>text/html;charset=UTF-8</value>
                            <value>application/json;charset=UTF-8</value>
                        </list>
                    </property>
                </bean>
            </mvc:message-converters>
        </mvc:annotation-driven>
    
        <!-- 静态资源配置 -->
        <mvc:resources mapping="/resources/**" location="/resources/"/>
    
        <!-- 对模型视图名称的解析,即在模型视图名称添加前后缀 -->
        <bean class="org.springframework.web.servlet.view.InternalResourceViewResolver">
            <property name="prefix" value="/"/>
            <property name="suffix" value=".jsp"/>
        </bean>
    
        <!-- 上传限制 -->
        <bean id="multipartResolver" class="org.springframework.web.multipart.commons.CommonsMultipartResolver">
            <!-- 上传文件大小限制为31M,31*1024*1024 -->
            <property name="maxUploadSize" value="32505856"/>
        </bean>
        
        <bean id="actionLogAdvice" class="com.zzxw.web.annotation.ActionLogAdvice" />
        <aop:config>
            <aop:pointcut id="actionLog" expression="execution(public * com.zzxw.web.controller..*..*(..)) " />
             <aop:advisor pointcut-ref="actionLog" advice-ref="actionLogAdvice"/>
        </aop:config>
        
        <!-- 总拦截器  -->
        <mvc:interceptors>
             <mvc:interceptor>
                <mvc:mapping path="/**" />
                <mvc:exclude-mapping path="/js/**" />
                <mvc:exclude-mapping path="/css/**" />
                <mvc:exclude-mapping path="/images/**" />
                <bean class="com.zzxw.web.interceptor.SpringRequestInterceptor" />
            </mvc:interceptor>
    
        </mvc:interceptors>

    6:spring-mybatis.xml

       <!-- 启动AspectJ支持   
        <aop:aspectj-autoproxy />--> 
        <context:property-placeholder location="classpath:config.properties" />
         <!-- 启用CGliB -->
    <!--     <aop:aspectj-autoproxy  /> -->
        
        
        <!-- 多个数据源的公用配置,方便下面直接引用 -->
         <bean id="abstractXADataSource" class="com.atomikos.jdbc.AtomikosDataSourceBean" init-method="init"
                 destroy-method="close" abstract="true">
            <property name="xaDataSourceClassName" value="oracle.jdbc.xa.client.OracleXADataSource"/>
            <property name="poolSize" value="10" />
            <property name="minPoolSize" value="10"/>
            <property name="maxPoolSize" value="30"/>
            <property name="borrowConnectionTimeout" value="60"/>
            <property name="reapTimeout" value="20"/>
            <property name="maxIdleTime" value="60"/>
            <property name="maintenanceInterval" value="60" />
            <property name="loginTimeout" value="60"/>
            <property name="logWriter" value="60"/>
            <property name="testQuery">
                <value>SELECT * from dual</value>
            </property>
        </bean> 
    <!--数据源A--> <bean id="dataSourceA" parent="abstractXADataSource"> <!-- value只要多个XA数据源之间不重复就行,随便取名 --> <property name="uniqueResourceName" value="dataPlat" /> <property name="xaDataSourceClassName" value="oracle.jdbc.xa.client.OracleXADataSource" /> <property name="xaProperties"> <props> <prop key="URL">${A_jdbc_url}</prop> <prop key="user">${A_jdbc_username}</prop> <prop key="password">${A_jdbc_password}</prop> </props> </property> </bean> <!--数据源B--> <bean id="dataSourceB" parent="abstractXADataSource"> <property name="uniqueResourceName" value="risk" /> <property name="xaDataSourceClassName" value="oracle.jdbc.xa.client.OracleXADataSource" /> <property name="xaProperties"> <props> <prop key="URL">${B_jdbc_url}</prop> <prop key="user">${B_jdbc_username}</prop> <prop key="password">${B_jdbc_password}</prop> </props> </property> </bean> <!-- Spring整合Mybatis,更多查看文档:http://mp.baomidou.com --> <bean id="sqlSessionFactory_A" class="com.baomidou.mybatisplus.spring.MybatisSqlSessionFactoryBean"> <property name="dataSource" ref="dataSourceA"/> <!-- 自动扫描Mapping.xml文件 --> <property name="mapperLocations" value="classpath:mybatis/dataplat/*.xml"/> <property name="configLocation" value="classpath:spring/mybatis-config.xml"/> <property name="typeAliasesPackage" value="com.zzxw.web.entity"/> <property name="plugins"> <array> <!-- 分页插件配置 --> <bean id="paginationInterceptor" class="com.baomidou.mybatisplus.plugins.PaginationInterceptor"> <property name="dialectType" value="oracle"/> </bean> </array> </property> <!-- 全局配置注入 --> <property name="globalConfig" ref="globalConfig" /> </bean> <!-- Spring整合Mybatis,更多查看文档:http://mp.baomidou.com --> <bean id="sqlSessionFactory_B" class="com.baomidou.mybatisplus.spring.MybatisSqlSessionFactoryBean"> <property name="dataSource" ref="dataSourceB"/> <!-- 自动扫描Mapping.xml文件 --> <property name="mapperLocations" value="classpath:mybatis/risk/*.xml"/> <property name="configLocation" value="classpath:spring/mybatis-config.xml"/>
    <!--对应的实体类--> <property name="typeAliasesPackage" value="com.zzxw.web.domain"/> <property name="plugins"> <array> <!-- 分页插件配置 --> <bean id="paginationInterceptor" class="com.baomidou.mybatisplus.plugins.PaginationInterceptor"> <property name="dialectType" value="oracle"/> </bean> </array> </property> <!-- 全局配置注入 --> <property name="globalConfig" ref="globalConfig" /> </bean> <!-- 配置多数据源 MultipleDataSource--> <bean name="dynamicDatasource" class="com.zzxw.web.common.DynamicDataSource"> <property name="targetDataSources"> <map> <!-- key和value-ref尽量保持一致,我在测试的时候因为名称不一致一致报错, 找了好久都没找到原因,最后统一了名称终于成功启动了 --> <entry key="dataSourceA" value-ref="dataSourceA"></entry> <entry key="dataSourceB" value-ref="dataSourceB"></entry> </map> </property> <!-- 指定一个默认的数据源,即在不需要切换数据源时,本地系统默认使用的数据源 --> <property name="defaultTargetDataSource" ref="dataSourceA" /> </bean> <bean id="dataSourceAspect" class="com.zzxw.web.common.DataSourceAspect"/> <aop:config> <aop:aspect ref="dataSourceAspect"> <aop:pointcut id="dataSourcePointcut" expression="execution(* com.zzxw.web.*.mapper.*.*(..))"/> <aop:before pointcut-ref="dataSourcePointcut" method="intercept" /> </aop:aspect> </aop:config> <!-- 配置自定义的SqlSessionTemplate模板,注入相关配置 --> <bean id="sqlSessionTemplate" class="com.zzxw.web.common.CustomSqlSessionTemplate" scope="prototype"> <!-- 构造注入参数指定本地默认数据源对应的SqlSessionFactoryBean --> <constructor-arg ref="sqlSessionFactory_A" /> <property name="targetSqlSessionFactorys"> <map> <!-- key和上文配置的数据源的id值尽量保持一致,我在测试的时候因为名称不一致一致报错, 找了好久都没找到原因,最后统一了名称终于成功启动了 --> <entry value-ref="sqlSessionFactory_A" key="dataSourceA"/> <entry value-ref="sqlSessionFactory_B" key="dataSourceB"/> </map> </property> </bean> <!-- MyBatis 动态扫描 --> <bean class="org.mybatis.spring.mapper.MapperScannerConfigurer"> <property name="basePackage" value="com.zzxw.web.**.mapper"/> <property name="sqlSessionTemplateBeanName" value="sqlSessionTemplate"/> </bean> <!-- jta配置开始 --> <bean id="atomikosTransactionManager" class="com.atomikos.icatch.jta.UserTransactionManager" init-method="init" destroy-method="close"> <property name="forceShutdown"> <value>true</value> </property> </bean> <bean id="atomikosUserTransaction" class="com.atomikos.icatch.jta.UserTransactionImp"> <property name="transactionTimeout" value="300" /> </bean> <bean id="springTransactionManager" class="org.springframework.transaction.jta.JtaTransactionManager"> <property name="transactionManager"> <ref bean="atomikosTransactionManager" /> </property> <property name="userTransaction"> <ref bean="atomikosUserTransaction" /> </property> </bean> <!-- jta配置结束 --> <!-- 配置事务管理 --> <tx:annotation-driven transaction-manager="springTransactionManager" proxy-target-class="true" /> <bean id="transactionManager" class="org.springframework.jdbc.datasource.DataSourceTransactionManager" p:dataSource-ref="dynamicDatasource"/> <bean id="globalConfig" class="com.baomidou.mybatisplus.entity.GlobalConfiguration"> <!-- AUTO->`0`("数据库ID自增") INPUT->`1`(用户输入ID") ID_WORKER->`2`("全局唯一ID") UUID->`3`("全局唯一ID") --> <property name="idType" value="3" /> <!-- MYSQL->`mysql` ORACLE->`oracle` DB2->`db2` H2->`h2` HSQL->`hsql` SQLITE->`sqlite` POSTGRE->`postgresql` SQLSERVER2005->`sqlserver2005` SQLSERVER->`sqlserver` --> <!-- Oracle需要添加该项 --> <property name="dbType" value="oracle" /> <!-- 全局表为下划线命名设置 true --> <property name="dbColumnUnderline" value="true" /> </bean>

    7:mybatis-config.xml

    <?xml version="1.0" encoding="UTF-8"?>
    <!DOCTYPE configuration PUBLIC "-//mybatis.org//DTD SQL Map Config 3.0//EN"
            "http://mybatis.org/dtd/mybatis-3-config.dtd">
    <!--
     |   plugins在配置文件中的位置必须符合要求,否则会报错,顺序如下:
     |   properties?, settings?,
     |   typeAliases?, typeHandlers?,
     |   objectFactory?,objectWrapperFactory?,
     |   plugins?,
     |   environments?, databaseIdProvider?, mappers?
     |-->
    <configuration>
        <!--
         | 全局配置设置
         |
         | 可配置选项                   默认值,     描述
         |
         | aggressiveLazyLoading       true,     当设置为‘true’的时候,懒加载的对象可能被任何懒属性全部加载。否则,每个属性都按需加载。
         | multipleResultSetsEnabled   true,     允许和不允许单条语句返回多个数据集(取决于驱动需求)
         | useColumnLabel              true,     使用列标签代替列名称。不同的驱动器有不同的作法。参考一下驱动器文档,或者用这两个不同的选项进行测试一下。
         | useGeneratedKeys            false,    允许JDBC 生成主键。需要驱动器支持。如果设为了true,这个设置将强制使用被生成的主键,有一些驱动器不兼容不过仍然可以执行。
         | autoMappingBehavior         PARTIAL,  指定MyBatis 是否并且如何来自动映射数据表字段与对象的属性。PARTIAL将只自动映射简单的,没有嵌套的结果。FULL 将自动映射所有复杂的结果。
         | defaultExecutorType         SIMPLE,   配置和设定执行器,SIMPLE 执行器执行其它语句。REUSE 执行器可能重复使用prepared statements 语句,BATCH执行器可以重复执行语句和批量更新。
         | defaultStatementTimeout     null,     设置一个时限,以决定让驱动器等待数据库回应的多长时间为超时
         | -->
        <settings>
            <!-- 这个配置使全局的映射器启用或禁用缓存 -->
            <setting name="cacheEnabled" value="true"/>
            <!-- 全局启用或禁用延迟加载。当禁用时,所有关联对象都会即时加载 -->
            <setting name="lazyLoadingEnabled" value="true"/>
            <setting name="multipleResultSetsEnabled" value="true"/>
            <setting name="useColumnLabel" value="true"/>
            <setting name="defaultExecutorType" value="REUSE"/>
            <setting name="defaultStatementTimeout" value="25000"/>
             <setting name="callSettersOnNulls" value="true"/>  
        </settings>
    
    </configuration>

    8:spring.xml

        <!-- 引入属性文件 -->
        <context:property-placeholder location="classpath:config.properties"/>
    
        <!-- Service包(自动注入) -->
        <context:component-scan base-package="com.zzxw.web.service"/>
    
        <import resource="classpath:spring/spring-mybatis.xml"/>

    9.CustomSqlSessionTemplate.java

    public class CustomSqlSessionTemplate extends SqlSessionTemplate {
        
        private final SqlSessionFactory sqlSessionFactory;
        private final ExecutorType executorType;
        private final SqlSession sqlSessionProxy;
        private final PersistenceExceptionTranslator exceptionTranslator;
     
        private Map<Object, SqlSessionFactory> targetSqlSessionFactorys;
        private SqlSessionFactory defaultTargetSqlSessionFactory;
     
        public void setTargetSqlSessionFactorys(Map<Object, SqlSessionFactory> targetSqlSessionFactorys) {
            this.targetSqlSessionFactorys = targetSqlSessionFactorys;
        }
     
        public void setDefaultTargetSqlSessionFactory(SqlSessionFactory defaultTargetSqlSessionFactory) {
            this.defaultTargetSqlSessionFactory = defaultTargetSqlSessionFactory;
        }
     
        public CustomSqlSessionTemplate(SqlSessionFactory sqlSessionFactory) {
            this(sqlSessionFactory, sqlSessionFactory.getConfiguration().getDefaultExecutorType());
        }
     
        public CustomSqlSessionTemplate(SqlSessionFactory sqlSessionFactory, ExecutorType executorType) {
            this(sqlSessionFactory, executorType, new MyBatisExceptionTranslator(sqlSessionFactory.getConfiguration()
                    .getEnvironment().getDataSource(), true));
        }
     
        public CustomSqlSessionTemplate(SqlSessionFactory sqlSessionFactory, ExecutorType executorType,
                PersistenceExceptionTranslator exceptionTranslator) {
     
            super(sqlSessionFactory, executorType, exceptionTranslator);
     
            this.sqlSessionFactory = sqlSessionFactory;
            this.executorType = executorType;
            this.exceptionTranslator = exceptionTranslator;
            
            this.sqlSessionProxy = (SqlSession) newProxyInstance(
                    SqlSessionFactory.class.getClassLoader(),
                    new Class[] { SqlSession.class }, 
                    new SqlSessionInterceptor());
     
            this.defaultTargetSqlSessionFactory = sqlSessionFactory;
        }
     
        @Override
        public SqlSessionFactory getSqlSessionFactory() {
     
            SqlSessionFactory targetSqlSessionFactory = targetSqlSessionFactorys.get(DynamicDataSourceHolder.getDataSource());
            if (targetSqlSessionFactory != null) {
                return targetSqlSessionFactory;
            } else if (defaultTargetSqlSessionFactory != null) {
                return defaultTargetSqlSessionFactory;
            } else {
                Assert.notNull(targetSqlSessionFactorys, "Property 'targetSqlSessionFactorys' or 'defaultTargetSqlSessionFactory' are required");
                Assert.notNull(defaultTargetSqlSessionFactory, "Property 'defaultTargetSqlSessionFactory' or 'targetSqlSessionFactorys' are required");
            }
            return this.sqlSessionFactory;
        }
     
        @Override
        public Configuration getConfiguration() {
            return this.getSqlSessionFactory().getConfiguration();
        }
     
        public ExecutorType getExecutorType() {
            return this.executorType;
        }
     
        public PersistenceExceptionTranslator getPersistenceExceptionTranslator() {
            return this.exceptionTranslator;
        }
     
        /**
         * {@inheritDoc}
         */
        public <T> T selectOne(String statement) {
            return this.sqlSessionProxy.<T> selectOne(statement);
        }
     
        /**
         * {@inheritDoc}
         */
        public <T> T selectOne(String statement, Object parameter) {
            return this.sqlSessionProxy.<T> selectOne(statement, parameter);
        }
     
        /**
         * {@inheritDoc}
         */
        public <K, V> Map<K, V> selectMap(String statement, String mapKey) {
            return this.sqlSessionProxy.<K, V> selectMap(statement, mapKey);
        }
     
        /**
         * {@inheritDoc}
         */
        public <K, V> Map<K, V> selectMap(String statement, Object parameter, String mapKey) {
            return this.sqlSessionProxy.<K, V> selectMap(statement, parameter, mapKey);
        }
     
        /**
         * {@inheritDoc}
         */
        public <K, V> Map<K, V> selectMap(String statement, Object parameter, String mapKey, RowBounds rowBounds) {
            return this.sqlSessionProxy.<K, V> selectMap(statement, parameter, mapKey, rowBounds);
        }
     
        /**
         * {@inheritDoc}
         */
        public <E> List<E> selectList(String statement) {
            return this.sqlSessionProxy.<E> selectList(statement);
        }
     
        /**
         * {@inheritDoc}
         */
        public <E> List<E> selectList(String statement, Object parameter) {
            return this.sqlSessionProxy.<E> selectList(statement, parameter);
        }
     
        /**
         * {@inheritDoc}
         */
        public <E> List<E> selectList(String statement, Object parameter, RowBounds rowBounds) {
            return this.sqlSessionProxy.<E> selectList(statement, parameter, rowBounds);
        }
     
        /**
         * {@inheritDoc}
         */
        public void select(String statement, ResultHandler handler) {
            this.sqlSessionProxy.select(statement, handler);
        }
     
        /**
         * {@inheritDoc}
         */
        public void select(String statement, Object parameter, ResultHandler handler) {
            this.sqlSessionProxy.select(statement, parameter, handler);
        }
     
        /**
         * {@inheritDoc}
         */
        public void select(String statement, Object parameter, RowBounds rowBounds, ResultHandler handler) {
            this.sqlSessionProxy.select(statement, parameter, rowBounds, handler);
        }
     
        /**
         * {@inheritDoc}
         */
        public int insert(String statement) {
            return this.sqlSessionProxy.insert(statement);
        }
     
        /**
         * {@inheritDoc}
         */
        public int insert(String statement, Object parameter) {
            return this.sqlSessionProxy.insert(statement, parameter);
        }
     
        /**
         * {@inheritDoc}
         */
        public int update(String statement) {
            return this.sqlSessionProxy.update(statement);
        }
     
        /**
         * {@inheritDoc}
         */
        public int update(String statement, Object parameter) {
            return this.sqlSessionProxy.update(statement, parameter);
        }
     
        /**
         * {@inheritDoc}
         */
        public int delete(String statement) {
            return this.sqlSessionProxy.delete(statement);
        }
     
        /**
         * {@inheritDoc}
         */
        public int delete(String statement, Object parameter) {
            return this.sqlSessionProxy.delete(statement, parameter);
        }
     
        /**
         * {@inheritDoc}
         */
        public <T> T getMapper(Class<T> type) {
            return getConfiguration().getMapper(type, this);
        }
     
        /**
         * {@inheritDoc}
         */
        public void commit() {
            throw new UnsupportedOperationException("Manual commit is not allowed over a Spring managed SqlSession");
        }
     
        /**
         * {@inheritDoc}
         */
        public void commit(boolean force) {
            throw new UnsupportedOperationException("Manual commit is not allowed over a Spring managed SqlSession");
        }
     
        /**
         * {@inheritDoc}
         */
        public void rollback() {
            throw new UnsupportedOperationException("Manual rollback is not allowed over a Spring managed SqlSession");
        }
     
        /**
         * {@inheritDoc}
         */
        public void rollback(boolean force) {
            throw new UnsupportedOperationException("Manual rollback is not allowed over a Spring managed SqlSession");
        }
     
        /**
         * {@inheritDoc}
         */
        public void close() {
            throw new UnsupportedOperationException("Manual close is not allowed over a Spring managed SqlSession");
        }
     
        /**
         * {@inheritDoc}
         */
        public void clearCache() {
            this.sqlSessionProxy.clearCache();
        }
     
        /**
         * {@inheritDoc}
         */
        public Connection getConnection() {
            return this.sqlSessionProxy.getConnection();
        }
     
        /**
         * {@inheritDoc}
         * @since 1.0.2
         */
        public List<BatchResult> flushStatements() {
            return this.sqlSessionProxy.flushStatements();
        }
     
        /**
         * Proxy needed to route MyBatis method calls to the proper SqlSession got from Spring's Transaction Manager It also
         * unwraps exceptions thrown by {@code Method#invoke(Object, Object...)} to pass a {@code PersistenceException} to
         * the {@code PersistenceExceptionTranslator}.
         */
        private class SqlSessionInterceptor implements InvocationHandler {
            public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
                final SqlSession sqlSession = getSqlSession(
                        CustomSqlSessionTemplate.this.getSqlSessionFactory(),
                        CustomSqlSessionTemplate.this.executorType, 
                        CustomSqlSessionTemplate.this.exceptionTranslator);
                try {
                    Object result = method.invoke(sqlSession, args);
                    if (!isSqlSessionTransactional(sqlSession, CustomSqlSessionTemplate.this.getSqlSessionFactory())) {
                        // force commit even on non-dirty sessions because some databases require
                        // a commit/rollback before calling close()
                        sqlSession.commit(true);
                    }
                    return result;
                } catch (Throwable t) {
                    Throwable unwrapped = unwrapThrowable(t);
                    if (CustomSqlSessionTemplate.this.exceptionTranslator != null && unwrapped instanceof PersistenceException) {
                        Throwable translated = CustomSqlSessionTemplate.this.exceptionTranslator
                            .translateExceptionIfPossible((PersistenceException) unwrapped);
                        if (translated != null) {
                            unwrapped = translated;
                        }
                    }
                    throw unwrapped;
                } finally {
                    closeSqlSession(sqlSession, CustomSqlSessionTemplate.this.getSqlSessionFactory());
                }
            }
        }
     
    }

    多数据源切换代码

    1、DynamicDataSource.java

    public class DynamicDataSource extends AbstractRoutingDataSource {
    
        @Override
        protected Object determineCurrentLookupKey() {
            // 从自定义的位置获取数据源标识
            return DynamicDataSourceHolder.getDataSource();
        }
    
    }

    2、DataSourceAspect.java

    public class DataSourceAspect {
    
        /**
         * 拦截目标方法,获取由@DataSource指定的数据源标识,设置到线程存储中以便切换数据源
         * 
         * @param point
         * @throws Exception
         */
        public void intercept(JoinPoint point) throws Exception {
            Class<?> target = point.getTarget().getClass();
            MethodSignature signature = (MethodSignature) point.getSignature();
            // 默认使用目标类型的注解,如果没有则使用其实现接口的注解
            for (Class<?> clazz : target.getInterfaces()) {
                resolveDataSource(clazz, signature.getMethod());
            }
            resolveDataSource(target, signature.getMethod());
        }
    
        /**
         * 提取目标对象方法注解和类型注解中的数据源标识
         * 
         * @param clazz
         * @param method
         */
        private void resolveDataSource(Class<?> clazz, Method method) {
            try {
                Class<?>[] types = method.getParameterTypes();
                // 默认使用类型注解
                if (clazz.isAnnotationPresent(DataSource.class)) {
                    DataSource source = clazz.getAnnotation(DataSource.class);
                    DynamicDataSourceHolder.setDataSource(source.value());
                }
                // 方法注解可以覆盖类型注解
                Method m = clazz.getMethod(method.getName(), types);
                if (m != null && m.isAnnotationPresent(DataSource.class)) {
                    DataSource source = m.getAnnotation(DataSource.class);
                    DynamicDataSourceHolder.setDataSource(source.value());
                }
            } catch (Exception e) {
                System.out.println(clazz + ":" + e.getMessage());
            }
        }
    
    }

    3、DynamicDataSourceHolder.java

    public class DynamicDataSourceHolder {
        /**
         * 注意:数据源标识保存在线程变量中,避免多线程操作数据源时互相干扰
         */
        private static final ThreadLocal<String> THREAD_DATA_SOURCE = new ThreadLocal<String>();
    
        public static String getDataSource() {
            return THREAD_DATA_SOURCE.get();
        }
    
        public static void setDataSource(String dataSource) {
            THREAD_DATA_SOURCE.set(dataSource);
        }
    
        public static void clearDataSource() {
            THREAD_DATA_SOURCE.remove();
        }
    
    }
  • 相关阅读:
    JDBC 实例--JDBC通过工具类DBUtil连接到数据库,让我们不再恐惧操作数据库
    揭开JDBC的神秘面纱,让JDBC数据库的连接参数不再神秘
    实验六 最小代价生成树
    实验五 背包问题和带时限的作业排序
    实验四 图的遍历算法设计与实现
    实验三 跳表算法设计与实现
    实验二 伸展树算法设计与实现
    算法实例一 算法问题求解基础--欧几里得递归算法和递归算法
    2013年 蓝桥杯预赛 java 本科A 题目
    java常用开发工具类之 图片水印,文字水印,缩放,补白工具类
  • 原文地址:https://www.cnblogs.com/lujiquan/p/7877869.html
Copyright © 2020-2023  润新知