国产探花免费观看_亚洲丰满少妇自慰呻吟_97日韩有码在线_资源在线日韩欧美_一区二区精品毛片,辰东完美世界有声小说,欢乐颂第一季,yy玄幻小说排行榜完本

首頁 > 編程 > Java > 正文

Spring+MyBatis多數據源配置實現示例

2019-11-26 13:11:12
字體:
來源:轉載
供稿:網友

最近用到了MyBatis配置多數據源,原以為簡單配置下就行了,實際操作后發現還是要費些事的,這里記錄下,以作備忘

不多廢話,直接上代碼,后面會有簡單的實現介紹

jdbc和log4j的配置

#定義輸出格式ConversionPattern=%d %-5p [%t] %c - %m%nlog4j.rootLogger=DEBUG,Consolelog4j.logger.com.cnblogs.lzrabbit=DEBUGlog4j.logger.org.springframework=ERRORlog4j.logger.org.mybatis=ERRORlog4j.logger.org.apache.ibatis=ERRORlog4j.logger.org.quartz=ERRORlog4j.logger.org.apache.axis2=ERRORlog4j.logger.org.apache.axiom=ERRORlog4j.logger.org.apache=ERRORlog4j.logger.httpclient=ERROR#log4j.additivity.org.springframework=false#Console log4j.appender.Console=org.apache.log4j.ConsoleAppenderlog4j.appender.Console.Threshold=DEBUG log4j.appender.Console.Target=System.out log4j.appender.Console.layout=org.apache.log4j.PatternLayout log4j.appender.Console.layout.ConversionPattern=${ConversionPattern}#log4j.appender.Console.encoding=UTF-8#org.apache.log4j.DailyRollingFileAppenderlog4j.appender.DailyFile=org.apache.log4j.DailyRollingFileAppenderlog4j.appender.DailyFile.DatePattern='.'yyyy-MM-dd'.log'log4j.appender.DailyFile.File=${myApp.root}/logs/daily.loglog4j.appender.DailyFile.Append=truelog4j.appender.DailyFile.Threshold=DEBUGlog4j.appender.DailyFile.layout=org.apache.log4j.PatternLayoutlog4j.appender.DailyFile.layout.ConversionPattern=${ConversionPattern}log4j.appender.DailyFile.encoding=UTF-8# %c 輸出日志信息所屬的類的全名 # %d 輸出日志時間點的日期或時間,默認格式為ISO8601,也可以在其后指定格式,比如:%d{yyy-MM-dd HH:mm:ss},輸出類似:2002-10-18- 22:10:28# %f 輸出日志信息所屬的類的類名 # %l 輸出日志事件的發生位置,即輸出日志信息的語句處于它所在的類的第幾行 # %m 輸出代碼中指定的信息,如log(message)中的message # %n 輸出一個回車換行符,Windows平臺為“rn”,Unix平臺為“n” # %p 輸出優先級,即DEBUG,INFO,WARN,ERROR,FATAL。如果是調用debug()輸出的,則為DEBUG,依此類推 # %r 輸出自應用啟動到輸出該日志信息所耗費的毫秒數 # %t 輸出產生該日志事件的線程名
#============================================================================# MySQL#============================================================================jdbc.mysql.driver=com.mysql.jdbc.Driverjdbc.mysql.url=jdbc:mysql://127.0.0.1:3306/test?useUnicode=true&characterEncoding=UTF-8&allowMultiQueries=truejdbc.mysql.username=rootjdbc.mysql.password=root#============================================================================# MS SQL Server#============================================================================#jdbc.sqlserver.driver=com.microsoft.sqlserver.jdbc.SQLServerDriver#jdbc.sqlserver.url=jdbc:sqlserver://127.0.0.1:1433;database=test;#jdbc.sqlserver.username=sa#jdbc.sqlserver.password=sa#============================================================================# MS SQL Server (JTDS)#============================================================================jdbc.sqlserver.driver=net.sourceforge.jtds.jdbc.Driverjdbc.sqlserver.url=jdbc:jtds:sqlserver://127.0.0.1:1433/testjdbc.sqlserver.username=sajdbc.sqlserver.password=sa#============================================================================# 通用配置#============================================================================jdbc.initialSize=5jdbc.minIdle=5jdbc.maxIdle=20jdbc.maxActive=100jdbc.maxWait=100000jdbc.defaultAutoCommit=falsejdbc.removeAbandoned=truejdbc.removeAbandonedTimeout=600jdbc.testWhileIdle=truejdbc.timeBetweenEvictionRunsMillis=60000jdbc.numTestsPerEvictionRun=20jdbc.minEvictableIdleTimeMillis=300000

單數據源時的Spring配置文件

<?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:context="http://www.springframework.org/schema/context"  xmlns:aop="http://www.springframework.org/schema/aop"  xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans-3.0.xsd http://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context-3.0.xsd  http://www.springframework.org/schema/aop   http://www.springframework.org/schema/aop/spring-aop-3.0.xsd"> <bean id="propertyConfigurer" class="org.springframework.beans.factory.config.PropertyPlaceholderConfigurer">  <property name="location" value="classpath:jdbc.properties"/> </bean>  <bean id="dataSource" class="org.apache.commons.dbcp.BasicDataSource" destroy-method="close">  <property name="driverClassName" value="${jdbc.mysql.driver}"/>  <property name="url" value="${jdbc.mysql.url}"/>  <property name="username" value="${jdbc.mysql.username}"/>  <property name="password" value="${jdbc.mysql.password}"/>  <property name="initialSize" value="${jdbc.initialSize}"/>  <property name="minIdle" value="${jdbc.minIdle}"/>  <property name="maxIdle" value="${jdbc.maxIdle}"/>  <property name="maxActive" value="${jdbc.maxActive}"/>  <property name="maxWait" value="${jdbc.maxWait}"/>  <property name="defaultAutoCommit" value="${jdbc.defaultAutoCommit}"/>  <property name="removeAbandoned" value="${jdbc.removeAbandoned}"/>  <property name="removeAbandonedTimeout" value="${jdbc.removeAbandonedTimeout}"/>  <property name="testWhileIdle" value="${jdbc.testWhileIdle}"/>  <property name="timeBetweenEvictionRunsMillis" value="${jdbc.timeBetweenEvictionRunsMillis}"/>  <property name="numTestsPerEvictionRun" value="${jdbc.numTestsPerEvictionRun}"/>  <property name="minEvictableIdleTimeMillis" value="${jdbc.minEvictableIdleTimeMillis}"/> </bean> <bean id="sqlSessionFactory" class="org.mybatis.spring.SqlSessionFactoryBean">  <property name="dataSource" ref="dataSource"/> </bean> <!-- mybatis.spring自動映射 --> <bean class="org.mybatis.spring.mapper.MapperScannerConfigurer">  <property name="basePackage" value="com.cnblogs.lzrabbit"/> </bean> <!-- 自動掃描,多個包以 逗號分隔 --> <context:component-scan base-package="com.cnblogs.lzrabbit"/> <aop:aspectj-autoproxy/></beans>

多數據源時Spring配置文件

<?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:context="http://www.springframework.org/schema/context"  xmlns:aop="http://www.springframework.org/schema/aop"  xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans-3.0.xsd http://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context-3.0.xsd  http://www.springframework.org/schema/aop   http://www.springframework.org/schema/aop/spring-aop-3.0.xsd"> <bean id="propertyConfigurer" class="org.springframework.beans.factory.config.PropertyPlaceholderConfigurer">  <property name="location" value="classpath:jdbc.properties"/> </bean> <bean id="sqlServerDataSource" class="org.apache.commons.dbcp.BasicDataSource" destroy-method="close">  <property name="driverClassName" value="${jdbc.sqlserver.driver}"/>  <property name="url" value="${jdbc.sqlserver.url}"/>  <property name="username" value="${jdbc.sqlserver.username}"/>  <property name="password" value="${jdbc.sqlserver.password}"/>  <property name="initialSize" value="${jdbc.initialSize}"/>  <property name="minIdle" value="${jdbc.minIdle}"/>  <property name="maxIdle" value="${jdbc.maxIdle}"/>  <property name="maxActive" value="${jdbc.maxActive}"/>  <property name="maxWait" value="${jdbc.maxWait}"/>  <property name="defaultAutoCommit" value="${jdbc.defaultAutoCommit}"/>  <property name="removeAbandoned" value="${jdbc.removeAbandoned}"/>  <property name="removeAbandonedTimeout" value="${jdbc.removeAbandonedTimeout}"/>  <property name="testWhileIdle" value="${jdbc.testWhileIdle}"/>  <property name="timeBetweenEvictionRunsMillis" value="${jdbc.timeBetweenEvictionRunsMillis}"/>  <property name="numTestsPerEvictionRun" value="${jdbc.numTestsPerEvictionRun}"/>  <property name="minEvictableIdleTimeMillis" value="${jdbc.minEvictableIdleTimeMillis}"/> </bean> <bean id="mySqlDataSource" class="org.apache.commons.dbcp.BasicDataSource" destroy-method="close">  <property name="driverClassName" value="${jdbc.mysql.driver}"/>  <property name="url" value="${jdbc.mysql.url}"/>  <property name="username" value="${jdbc.mysql.username}"/>  <property name="password" value="${jdbc.mysql.password}"/>  <property name="initialSize" value="${jdbc.initialSize}"/>  <property name="minIdle" value="${jdbc.minIdle}"/>  <property name="maxIdle" value="${jdbc.maxIdle}"/>  <property name="maxActive" value="${jdbc.maxActive}"/>  <property name="maxWait" value="${jdbc.maxWait}"/>  <property name="defaultAutoCommit" value="${jdbc.defaultAutoCommit}"/>  <property name="removeAbandoned" value="${jdbc.removeAbandoned}"/>  <property name="removeAbandonedTimeout" value="${jdbc.removeAbandonedTimeout}"/>  <property name="testWhileIdle" value="${jdbc.testWhileIdle}"/>  <property name="timeBetweenEvictionRunsMillis" value="${jdbc.timeBetweenEvictionRunsMillis}"/>  <property name="numTestsPerEvictionRun" value="${jdbc.numTestsPerEvictionRun}"/>  <property name="minEvictableIdleTimeMillis" value="${jdbc.minEvictableIdleTimeMillis}"/> </bean> <bean id="multipleDataSource" class="com.cnblogs.lzrabbit.MultipleDataSource">  <property name="defaultTargetDataSource" ref="mySqlDataSource"/>  <property name="targetDataSources">   <map>    <entry key="mySqlDataSource" value-ref="mySqlDataSource"/>    <entry key="sqlServerDataSource" value-ref="sqlServerDataSource"/>   </map>  </property> </bean> <bean id="sqlSessionFactory" class="org.mybatis.spring.SqlSessionFactoryBean">  <property name="dataSource" ref="multipleDataSource"/> </bean> <!-- mybatis.spring自動映射 --> <bean class="org.mybatis.spring.mapper.MapperScannerConfigurer">  <property name="basePackage" value="com.cnblogs.lzrabbit"/> </bean> <!-- 自動掃描,多個包以 逗號分隔 --> <context:component-scan base-package="com.cnblogs.lzrabbit"/> <aop:aspectj-autoproxy/></beans>

MultipleDataSource實現

package com.cnblogs.lzrabbit;import org.springframework.jdbc.datasource.lookup.AbstractRoutingDataSource;/** * Created by rabbit on 14-5-25. */public class MultipleDataSource extends AbstractRoutingDataSource { private static final ThreadLocal<String> dataSourceKey = new InheritableThreadLocal<String>(); public static void setDataSourceKey(String dataSource) {  dataSourceKey.set(dataSource); } @Override protected Object determineCurrentLookupKey() {  return dataSourceKey.get(); }}

MyBatis接口Mapper定義,直接使用注解方式實現

public interface MySqlMapper { @Select("select * from MyTable") List<Map<String,Object>> getList();}public interface SqlServerMapper {  @Select("select * from MyTable")  List<Map<String,Object>> getList();}

手動數據源切換調用

package com.cnblogs.lzrabbit;import org.springframework.context.ApplicationContext;import org.springframework.context.support.ClassPathXmlApplicationContext;/** * Created by rabbit on 14-5-25. */public class Main { public static void main(String[] args) {  //初始化ApplicationContext  ApplicationContext applicationContext = new ClassPathXmlApplicationContext("applicationContext.xml");  MySqlMapper mySqlMapper = applicationContext.getBean(MySqlMapper.class);  SqlServerMapper sqlServerMapper = applicationContext.getBean(SqlServerMapper.class);    //設置數據源為MySql,使用了AOP測試時請將下面這行注釋  MultipleDataSource.setDataSourceKey("mySqlDataSource");  mySqlMapper.getList();  //設置數據源為SqlServer,使用AOP測試時請將下面這行注釋  MultipleDataSource.setDataSourceKey("sqlServerDataSource");  sqlServerMapper.getList(); }}

使用SpringAOP方式實現自動切換

package com.cnblogs.lzrabbit;import org.aspectj.lang.ProceedingJoinPoint;import org.aspectj.lang.annotation.Around;import org.aspectj.lang.annotation.Aspect;import org.springframework.stereotype.Component;@Component@Aspectpublic class MultipleDataSourceAspectAdvice { @Around("execution(* com.cnblogs.lzrabbit.*.*(..))") public Object doAround(ProceedingJoinPoint jp) throws Throwable {  if (jp.getTarget() instanceof MySqlMapper) {   MultipleDataSource.setDataSourceKey("mySqlDataSource");  } else if (jp.getTarget() instanceof SqlServerMapper) {   MultipleDataSource.setDataSourceKey("sqlServerDataSource");  }  return jp.proceed(); }}

調用日志

2014-05-25 20:02:04,319 DEBUG [main] com.jb51.lzrabbit.MySqlMapper.getList - ooo Using Connection [jdbc:mysql://127.0.0.1:3306/test?useUnicode=true&characterEncoding=UTF-8&allowMultiQueries=true, UserName=root@192.168.1.32, MySQL Connector Java]2014-05-25 20:02:04,333 DEBUG [main] com.jb51.lzrabbit.MySqlMapper.getList - ==> Preparing: select * from MyTable 2014-05-25 20:02:04,371 DEBUG [main] com.jb51.lzrabbit.MySqlMapper.getList - ==> Parameters: 2014-05-25 20:02:04,396 DEBUG [main] com.jb51.lzrabbit.MySqlMapper.getList - <==  Total: 82014-05-25 20:02:04,620 DEBUG [main] com.jb51.lzrabbit.SqlServerMapper.getList - ooo Using Connection [jdbc:jtds:sqlserver://127.0.0.1:1433/test, UserName=sa, jTDS Type 4 JDBC Driver for MS SQL Server and Sybase]2014-05-25 20:02:04,620 DEBUG [main] com.jb51.lzrabbit.SqlServerMapper.getList - ==> Preparing: select * from TmallCityMap 2014-05-25 20:02:04,621 DEBUG [main] com.jb51.lzrabbit.SqlServerMapper.getList - ==> Parameters: 2014-05-25 20:02:04,681 DEBUG [main] com.jb51.lzrabbit.SqlServerMapper.getList - <==  Total: 397

這里就上面的實現做個簡單解釋,在我們配置單數據源時可以看到數據源類型使用了org.apache.commons.dbcp.BasicDataSource,而這個代碼實現了javax.sql.DataSource接口

配置sqlSessionFactory時org.mybatis.spring.SqlSessionFactoryBean注入參數dataSource類型就是javax.sql.DataSource

實現多數據源的方法就是我們自定義了一個MultipleDataSource,這個類繼承自AbstractRoutingDataSource,而AbstractRoutingDataSource繼承自AbstractDataSource ,AbstractDataSource 實現了javax.sql.DataSource接口,所以我們的MultipleDataSource也實現了javax.sql.DataSource接口,可以賦值給sqlSessionFactory的dataSource屬性

public abstract class AbstractRoutingDataSource extends AbstractDataSource implements InitializingBean {}public abstract class AbstractDataSource implements DataSource {}

再來說下MultipleDataSource的實現原理,MultipleDataSource實現AbstractRoutingDataSource抽象類,然后實現了determineCurrentLookupKey方法,這個方法用于選擇具體使用targetDataSources中的哪一個數據源

<bean id="multipleDataSource" class="com.cnblogs.lzrabbit.MultipleDataSource">  <property name="defaultTargetDataSource" ref="mySqlDataSource"/>  <property name="targetDataSources">   <map>    <entry key="mySqlDataSource" value-ref="mySqlDataSource"/>    <entry key="sqlServerDataSource" value-ref="sqlServerDataSource"/>   </map>  </property> </bean>

可以看到Spring配置中multipleDataSource設置了兩個屬性defaultTargetDataSource和targetDataSources,這兩個屬性定義在AbstractRoutingDataSource,當MyBatis執行查詢時會先選擇數據源,選擇順序時現根據determineCurrentLookupKey方法返回的值到targetDataSources中去找,若能找到怎返回對應的數據源,若找不到返回默認的數據源defaultTargetDataSource,具體參考AbstractRoutingDataSource的源碼

public abstract class AbstractRoutingDataSource extends AbstractDataSource implements InitializingBean { private Map<Object, Object> targetDataSources; private Object defaultTargetDataSource;  /**  * Retrieve the current target DataSource. Determines the  * {@link #determineCurrentLookupKey() current lookup key}, performs  * a lookup in the {@link #setTargetDataSources targetDataSources} map,  * falls back to the specified  * {@link #setDefaultTargetDataSource default target DataSource} if necessary.  * @see #determineCurrentLookupKey()  */ protected DataSource determineTargetDataSource() {  Assert.notNull(this.resolvedDataSources, "DataSource router not initialized");  Object lookupKey = determineCurrentLookupKey();  DataSource dataSource = this.resolvedDataSources.get(lookupKey);  if (dataSource == null && (this.lenientFallback || lookupKey == null)) {   dataSource = this.resolvedDefaultDataSource;  }  if (dataSource == null) {   throw new IllegalStateException("Cannot determine target DataSource for lookup key [" + lookupKey + "]");  }  return dataSource; } /**  * Determine the current lookup key. This will typically be  * implemented to check a thread-bound transaction context.  * <p>Allows for arbitrary keys. The returned key needs  * to match the stored lookup key type, as resolved by the  * {@link #resolveSpecifiedLookupKey} method.  */ protected abstract Object determineCurrentLookupKey();    .............}

在動態切換數據源方法時選擇了AOP方式實現,這里實現的簡單粗暴,具體應用時根據實際需要靈活變通吧 

題外話,這里提下SqlServer驅動選擇的問題,目前SqlServer的驅動主要有微軟的官方驅動和JTDS驅動兩種,關于這兩個驅動我做過測試,批量更新,在小數據量(100以下)時,JTDS相對微軟驅動性能稍微高一點點,在數據量增大時幾萬到上百萬時,微軟驅動有著明顯優勢,所以若對性能比較敏感,建議使用微軟驅動,否則隨意

微軟驅動在Maven庫找不到,這點比較郁悶,若使用maven的話還得先安裝到本地,這點很不爽

JTDS使用比較方便Maven直接引用即可

相關jar maven引用

<properties>  <project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>  <org.springframework.version>3.2.7.RELEASE</org.springframework.version> </properties> <dependencies>  <dependency>   <groupId>org.aspectj</groupId>   <artifactId>aspectjweaver</artifactId>   <version>1.7.2</version>  </dependency>  <dependency>   <groupId>commons-dbcp</groupId>   <artifactId>commons-dbcp</artifactId>   <version>1.4</version>  </dependency>  <dependency>   <groupId>commons-logging</groupId>   <artifactId>commons-logging</artifactId>   <version>1.1.3</version>  </dependency>  <dependency>   <groupId>log4j</groupId>   <artifactId>log4j</artifactId>   <version>1.2.17</version>  </dependency>  <dependency>   <groupId>org.springframework</groupId>   <artifactId>spring-core</artifactId>   <version>${org.springframework.version}</version>  </dependency>  <dependency>   <groupId>org.springframework</groupId>   <artifactId>spring-beans</artifactId>   <version>${org.springframework.version}</version>  </dependency>  <dependency>   <groupId>org.springframework</groupId>   <artifactId>spring-aop</artifactId>   <version>${org.springframework.version}</version>  </dependency>  <dependency>   <groupId>org.springframework</groupId>   <artifactId>spring-context</artifactId>   <version>${org.springframework.version}</version>  </dependency>  <dependency>   <groupId>org.springframework</groupId>   <artifactId>spring-jdbc</artifactId>   <version>${org.springframework.version}</version>  </dependency>  <dependency>   <groupId>org.springframework</groupId>   <artifactId>spring-context-support</artifactId>   <version>${org.springframework.version}</version>  </dependency>  <dependency>   <groupId>org.springframework</groupId>   <artifactId>spring-web</artifactId>   <version>${org.springframework.version}</version>  </dependency>  <dependency>   <groupId>org.springframework</groupId>   <artifactId>spring-webmvc</artifactId>   <version>${org.springframework.version}</version>  </dependency>  <dependency>   <groupId>org.springframework</groupId>   <artifactId>spring-tx</artifactId>   <version>${org.springframework.version}</version>  </dependency>  <dependency>   <groupId>org.mybatis</groupId>   <artifactId>mybatis</artifactId>   <version>3.2.4</version>  </dependency>  <dependency>   <groupId>org.mybatis</groupId>   <artifactId>mybatis-spring</artifactId>   <version>1.2.2</version>  </dependency>  <dependency>   <groupId>org.slf4j</groupId>   <artifactId>slf4j-log4j12</artifactId>   <version>1.7.6</version>  </dependency>  <dependency>   <groupId>net.sourceforge.jtds</groupId>   <artifactId>jtds</artifactId>   <version>1.2.8</version>  </dependency>  <dependency>   <groupId>mysql</groupId>   <artifactId>mysql-connector-java</artifactId>   <version>5.1.29</version>  </dependency> </dependencies>

以上就是本文的全部內容,希望對大家的學習有所幫助,也希望大家多多支持武林網。

發表評論 共有條評論
用戶名: 密碼:
驗證碼: 匿名發表
主站蜘蛛池模板: 华宁县| 洱源县| 翁牛特旗| 类乌齐县| 丰原市| 潜山县| 盘山县| 孟津县| 和田市| 合肥市| 乌审旗| 五峰| 资兴市| 庆城县| 福海县| 巴马| 镇安县| 巴彦淖尔市| 定日县| 武定县| 郑州市| 突泉县| 元谋县| 承德县| 安平县| 滦南县| 崇义县| 抚顺市| 左权县| 阿坝县| 永登县| 开远市| 米泉市| 西丰县| 泉州市| 莱西市| 广河县| 子洲县| 榆中县| 南涧| 浦东新区|