wordybear之STS下spring boot、mybatis多数据源配置完全攻略及源码工程

// 2017.09.01 本文所依赖的开发环境早已更改为intellij idea,然而并不影响任何

本文面对初学者,在对基础有些了解但又似懂非懂有些混乱的情况下(作者一般学习新技的最初状态,此时需要冷静)。

但是,仔细阅读本文,将会在相同或相似的环境下实现sts下spring boot、mybatis多数据源的配置。多数据源,在项目中,真的常用。

本文给出最终实现细节的同时,另一个目的是对最近几天的学习探索进行流水式记录,很多踩到的坑儿,你或许也会经历,请耐心。

注:虽然已经可以搜到大量的指明完成本文工作的文章,但测试后要么感觉新手无法胜任、要么无法实现、要么不完整,本文力求从无到有(除了建立mysql、sql server2005数据库)。

 

1、背景

spring、mybatis的按部就班操作已经不少时日了,然而内心一直想做一套从架构上感觉很爽的方案,正好最近的一个项目让我觉得有必要仔细规划一下。

在以前的项目开发上,由于硬件配置受限、既有方案等,一直使用的开发环境版本很落后,这次趁自己升级了电脑配置,将要做的项目也算从0配置,因此最终选定了使用当前版本的sts(3.8.4.RELEASE)下spring boot的方式。

由于一直认为业务性的系统框架与具体的开发环境、语言等通常弱相关,因此当前的重点是测试性的完成系统实现需要的某些技术细节的准备,本文是为了解决项目中经常需要的多数据源访问配置问题。

 

2、环境

Spring ToolSuite(STS):

3.8.4.RELEASE;

64位版本;

http://download.springsource.com/release/STS/3.8.4.RELEASE/dist/e4.6/spring-tool-suite-3.8.4.RELEASE-e4.6.3-win32-x86_64.zip

jdk:

    jdk-7u75-windows-x64

maven:

    apache-maven-3.3.1-bin(未使用sts自带)

其他组件:

    Druid、sqljdbc4、mysql(这些都可通过pom进行配置)

注意:开发spring boot时,一定要联网(见《springboot实战》的说明)

 

3、spring与mybatis的配置

由于对spring boot的一片茫然,在最开始折腾时,混乱中也忘记了spring boot本来也仅是多加了一层功能用于简化配置,在它之中集成mybatis其实也是对原先spring+mybatis的mybatis.xml文件进行xml配置注解化,这本来是一个有效突破口的(可惜最初根本没思考),即注解最终必须等价于过去xml配置的效果才算是有效完成。无论对单一数据源,还是多个数据源,这个突破口都应该适用。外加一句,仅使用spring+jdbc,想要注解化,上面的原则也适用。

mybatis.xml的一般内容如下:




	
	
		
		
		
		
		
		
		
		
		
		
		
		
		
		
	
	
	
		
		
		
	
	   
             
      
	
	
		
		
	
	
	
		
	  


在spring自动扫描时,依据上面的xml配置与mybatis进行整合。

 

4、spring boot中注解实现应该做的事情

按照spring与mybatis的xml配置顺序,在使用注解时,对单一数据源配置,需要按照以下顺序进行:

一、读取数据源参数配置;

二、使用数据源参数创建一个数据源dataSource(本文使用DruidDataSource) bean;

三、由dataSource bean创建一个sqlSessionFactorybean;

四、由sqlSessionFactory bean创建一个sqlSessionTemplatebean;

五、由sqlSessionFactory、sqlSessionTemplate创建MapperScannerConfigurer bean;(此步非常重要,必须建立在三、四的基础之上);

六、事务管理bean,基于第一步的dataSource bean建立。

 

对多数据源,在spring boot中使用mybatis,与单一数据源具有不同的特点,重要的几点:

一、若不同数据源配置文件采用不同的.properties文件(所有配置文件内的属性都相同,仅属性值不同),则你可能无法使用org.springframework.beans.factory.config.PropertyPlaceholderConfigurer类进行配置,因为每个配置文件里的属性都相同,从直观上来看,至少后来者会覆盖先前的属性值,你可能也无法使用Environment类(我没有深入,也可能是我的用法不对),与PropertyPlaceholderConfigurer的问题类似。

你需要在某个mybatis注解配置类中,使用java.util.Properties类,手动的去加载配置文件,目前我觉得这也是一种不错的方案,至少可以保障所有的配置文件属性统一,示例如下:

jdbc.driverClassName=com.microsoft.sqlserver.jdbc.SQLServerDriver
jdbc.url=jdbc:sqlserver://127.0.0.1:1433;databaseName=testdb02;integratedSecurity=false
jdbc.username=sa
jdbc.password=password

jdbc.initialSize=5
jdbc.minIdle=5
jdbc.maxActive=20
jdbc.maxWait=60000
jdbc.timeBetweenEvictionRunsMillis=60000
jdbc.minEvictableIdleTimeMillis=300000
jdbc.poolPreparedStatements=true
jdbc.maxPoolPreparedStatementPerConnectionSize=20

jdbc.filters=stat,wall

#mybatis
mybatis.configLocation=classpath:/mb/mb-cfg-sql2v5-testdb02.xml
mybatis.typeAliasesPackage=com.zcn.swc.domain.testdb02.model
mybatis.mapperLocations=classpath*:/**/testdb02/mapper/*.xml


 

我的配置不是想做成下面这种形式:

#dataSourceAAA.properties文件内属性

spring.mysql.url=

spring.mysql.username=

 

#dataSrouceBBB.properties文件内属性

spring.sqlserver.url=

spring.sqlserver.username=

 

二、对由注解生成的相关bean,你需要指定其name。默认spring会将数据源相关的bean name指定为dataSource、sqlSessionFactory等等。但是对多数据源来说,你需要主动指定bean name。

三、根据spring boot的规则,你需要使用@Primary首先指定一套默认的数据体系。在本例中,我们将把mysql的数据库配置作为默认的数据库配置(后文会标注)。

 

5、实现

5.1 工程建立

在sts下,选择新建一个spring bootstarter工程,name为mbbase,type为maven,packaging为war,java version为1.7,language为java,group 为com.zcn,artifact为mbbase,version为0.0.1-SNAPSHOT,package为com.zcn.swc;

“下一步”后,选择依赖AOP、DevTools、Thymeleaf、Web,(我自己在pom.xml中指定了mybatis、mybatis-spring、mysql、sqlserver等的依赖了);

“完成”后即建立了一个spring-boot工程。

最终,经过手工修改后的pom.xml如下(可能有配置重复不合理的地方,但当前可以运行):




	4.0.0

	com.zcn
	mbbase
	0.0.1-SNAPSHOT
	war

	mbbase
	mbbase project for Spring Boot

	
		org.springframework.boot
		spring-boot-starter-parent
		1.5.2.RELEASE
		 
	

	
		UTF-8
		UTF-8
		1.7
	

	
		
			org.springframework.boot
			spring-boot-starter-aop
		
		
			org.springframework.boot
			spring-boot-starter-thymeleaf
		
		
			org.springframework.boot
			spring-boot-starter-web
		

		
			org.springframework.boot
			spring-boot-devtools
			runtime
		
		
			mysql
			mysql-connector-java
			runtime
		
		
			org.springframework.boot
			spring-boot-starter-tomcat
			provided
		
		
			org.springframework.boot
			spring-boot-starter-test
			test
		
		
		
		    org.springframework
		    spring-tx
		
		
		
		    org.springframework
		    spring-jdbc
		

		
		
		    org.mybatis
		    mybatis
		    3.4.1
		
		
             org.mybatis
             mybatis-spring
             1.3.1
            
		
		
		    com.alibaba
		    druid
		    1.0.18
		
		

		
		
		    com.microsoft.sqlserver
		    sqljdbc4
		    4.0
		

		
			javax.inject
			javax.inject
			1
		
	

	
		
			
				org.springframework.boot
				spring-boot-maven-plugin
			
			  
                org.mybatis.generator  
                mybatis-generator-maven-plugin  
                1.3.5  
                  
                    true  
                  
                  
                      
                        mysql  
                        mysql-connector-java  
                        5.1.30  
                    
					
						com.microsoft.sqlserver
						sqljdbc4
						4.0
					
                  
              
		
	



 

5.2 sts中使用mybatis-generator生成entity、mapper及xml等

本步骤是为了生成mybatis方式操作数据库的相关文件,与配置多数据源没有直接关系,如果你已经能够在sts内集成并生成相关文件了,可以跳过此步。

前提:在5.1步pom.xml中,我们已经配置好了mybatis-generator-maven-plugin插件。已经建立了三个数据库(一个mysql数据库名为phpmyadmin,两个sql server数据库名为testdb、testdb02)。

首先,我们建立mybatis-generator需要使用的配置文件。STS的Navigator view下,在/src/main/resources下,新建一个文件夹mbg,在其中建立三个xml文件:mbg-mysql-phpmyadmin.xml、mbg-sql2v5-testdb.xml、mbg-sql2v5-testdb02.xml(文件内容在本节之后附),特别注意,xml文件的格式是utf-8(无BOM)。

然后,以生成mysql-phpmyadmin数据库的mybatis相关文件的maven命令为例。右键点击mbbase工程,选择run as…,选择菜单项“Mavenbuild…”;在弹出的“EditConfiguration”对话框中,Name设置为“mbtest-mbg-mysql-phpmyadmin”(按习惯起的),Goals设置为:mybatis-generator:generate-Dmybatis.generator.configurationFile=${basedir}/src/main/resources/mbg/mbg-mysql-phpmyadmin.xml-Dmybatis.generator.overwrite=true。若是mbg-mysql-phpmyadmin.xml的内容已经设置好了,就可以点击Run运行了,否则选点击“Apply”保存吧。对mbbase-mbg-sql2v5-testdb、mbbase-mbg-sql2v5-testdb02,其相应的maven命令设置如下:

// mbbase-mbg-sql2v5-testdb

Name:mbbase-mbg-sql2v5-testdb

Goals:mybatis-generator:generate-Dmybatis.generator.configurationFile=${basedir}/src/main/resources/mbg/mbg-sql2v5-testdb.xml-Dmybatis.generator.overwrite=true

 

// mbbase-mbg-sql2v5-testdb02

Name:mbbase-mbg-sql2v5-testdb02

Goals:mybatis-generator:generate-Dmybatis.generator.configurationFile=${basedir}/src/main/resources/mbg/mbg-sql2v5-testdb02.xml-Dmybatis.generator.overwrite=true

 

通过运行以上三个maven命令,即可在com.zcn.swc下生成的domain包内,生成三个子包:phpmyadmin、tesddb、testdb02。其中包含了各自的mapper、model。

注意:生成的MPma_userconfigMapper.xml文件(mysql中的phpmyadmin库)内,会出现“phpmyadmin..pma_userconfig”(注意其中的两个dot),需要全部替换成“phpmyadmin.pma_userconfig”。

 

附:xml配置文件

注意,在mysql与sqlserver配置文件中,有几个不同:

driverClass不同;

connectionURL不同;

下面的不同,mysql仅需包含一个runtimeCatalog,sqlserver还需包含runtimeSchema,如果不这样,我这里生成的***mapper.xml内的sql语句就无法正确执行。

 

 

mbg-mysql-phpmyadmin.xml


  
  

      
          
              
              
          

          
          
          
              
          

          
              
              
          

          
              
		
				
          
              
          

        

mbg-sql2v5-testdb.xml



  
  

      
          
              
              
          

          
          
          
              
          

          
              
              
          

          
              
		
				
          
              
          

        	
        	
        

mbg-sql2v5-testdb02.xml



  
  

      
          
              
              
          

          
          
          
              
          

          
              
              
          

          
              
		
				
          
              
          

        	
        	
        

5.3 多数据源配置文件创建

在/src/main/resources下,新建一个文件夹mb,在其中建立三个数据源的配置文件:

//mysql-phpmyadmin:

数据源:mb-mysql-phpmyadmin.properties(文件格式utf-8无BOM)

mybatis参数:mb-cfg-mysql-phpmyadmin.xml(文件格式utf-8无BOM)

 

// sql2v5-testdb:

数据源:mb-sql2v5-testdb.properties(文件格式utf-8无BOM)

mybatis参数:mb-cfg- sql2v5-testdb.xml(文件格式utf-8无BOM)

 

//sql2v5-testdb02:

数据源:mb-sql2v5-testdb02.properties(文件格式utf-8无BOM)

mybatis参数:mb-cfg- sql2v5-testdb02.xml(文件格式utf-8无BOM)

 

附:配置文件内容

 

mb-mysql-phpmyadmin.properties

jdbc.driverClassName=com.mysql.jdbc.Driver
jdbc.url=jdbc:mysql://127.0.0.1:3306/phpmyadmin?useUnicode=true&characterEncoding=utf8
jdbc.username=root
jdbc.password=

jdbc.initialSize=5
jdbc.minIdle=5
jdbc.maxActive=20
jdbc.maxWait=60000
jdbc.timeBetweenEvictionRunsMillis=60000
jdbc.minEvictableIdleTimeMillis=300000
jdbc.poolPreparedStatements=true
jdbc.maxPoolPreparedStatementPerConnectionSize=20

jdbc.filters=stat,wall

#mybatis
mybatis.configLocation=classpath:/mb/mb-cfg-mysql-phpmyadmin.xml
mybatis.typeAliasesPackage=com.zcn.swc.domain.phpmyadmin.mapper.phpmyadmin
mybatis.mapperLocations=classpath*:/**/phpmyadmin/mapper/*.xml

mb-cfg-mysql-phpmyadmin.xml






    
        
    
    
        
        
        
        
        
        
        
        
        
        
        
        
        
        
        
        
    

	
		
	 

    

mb-sql2v5-testdb.properties


jdbc.driverClassName=com.microsoft.sqlserver.jdbc.SQLServerDriver
jdbc.url=jdbc:sqlserver://127.0.0.1:1433;databaseName=testdb;integratedSecurity=false
jdbc.username=sa
jdbc.password=password

jdbc.initialSize=5
jdbc.minIdle=5
jdbc.maxActive=20
jdbc.maxWait=60000
jdbc.timeBetweenEvictionRunsMillis=60000
jdbc.minEvictableIdleTimeMillis=300000
jdbc.poolPreparedStatements=true
jdbc.maxPoolPreparedStatementPerConnectionSize=20

jdbc.filters=stat,wall

#mybatis
mybatis.configLocation=classpath:/mb/mb-cfg-sql2v5-testdb.xml
mybatis.typeAliasesPackage=com.zcn.swc.domain.testdb.model
mybatis.mapperLocations=classpath*:/**/testdb/mapper/*.xml

mb-cfg-sql2v5-testdb.xml





    
        
    
    
        
        
        
        
        
        
        
        
        
        
        
        
        
        
        
        
    
    
    
				
	 

    

mb-sql2v5-testdb02.properties


jdbc.driverClassName=com.microsoft.sqlserver.jdbc.SQLServerDriver
jdbc.url=jdbc:sqlserver://127.0.0.1:1433;databaseName=testdb02;integratedSecurity=false
jdbc.username=sa
jdbc.password=password

jdbc.initialSize=5
jdbc.minIdle=5
jdbc.maxActive=20
jdbc.maxWait=60000
jdbc.timeBetweenEvictionRunsMillis=60000
jdbc.minEvictableIdleTimeMillis=300000
jdbc.poolPreparedStatements=true
jdbc.maxPoolPreparedStatementPerConnectionSize=20

jdbc.filters=stat,wall

#mybatis
mybatis.configLocation=classpath:/mb/mb-cfg-sql2v5-testdb02.xml
mybatis.typeAliasesPackage=com.zcn.swc.domain.testdb02.model
mybatis.mapperLocations=classpath*:/**/testdb02/mapper/*.xml

mb-cfg- sql2v5-testdb02.xml






    
        
    
    
        
        
        
        
        
        
        
        
        
        
        
        
        
        
        
        
    
    
    
				
	 

    

5.4 建立三个mybatis config类

本步骤是spring boot内配置多个mybatis数据源的最后一步。

首先,在com.zcn.swc下新建一个包common,然后建立三个config类:

MyBatis_Mysql_phpmyadmin_Config;

MyBatis_Sql2v5_testdb_Config;

MyBatis_Sql2v5_testdb02_Config;

在后面附的代码中,需要注意:

一、MyBatis_Mysql_phpmyadmin_Config类中的bean使用了@Primary注解;

二、mapperScannerConfigurer方法上,使用了@DependsOn注解。

以上两个非常关键,一是为了满足spring boot的默认规则,二是为了满足创建bean的顺序。

 

附:三个类文件:

 

// MyBatis_Mysql_phpmyadmin_Config

package com.zcn.swc.common;

import java.io.IOException;
import java.util.Properties;

import javax.sql.DataSource;

import org.apache.ibatis.session.SqlSessionFactory;
import org.mybatis.spring.SqlSessionFactoryBean;
import org.mybatis.spring.SqlSessionTemplate;
import org.mybatis.spring.mapper.MapperScannerConfigurer;
import org.springframework.beans.factory.annotation.Qualifier;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.context.annotation.DependsOn;
import org.springframework.context.annotation.Primary;
import org.springframework.core.io.support.PathMatchingResourcePatternResolver;
import org.springframework.jdbc.datasource.DataSourceTransactionManager;

import com.alibaba.druid.pool.DruidDataSource;

@Configuration 
public class MyBatis_Mysql_phpmyadmin_Config { 
	
	Properties _propsConfig = new Properties();
	
	public MyBatis_Mysql_phpmyadmin_Config() {
		// TODO Auto-generated constructor stub
        
        String filename = "mb/mb-mysql-phpmyadmin.properties";  
        try {
			_propsConfig.load(MyBatis_Mysql_phpmyadmin_Config.class.getClassLoader().getResourceAsStream(filename));
		} catch (IOException e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
		}          
	}

    @Bean(name = "dataSource_mysql_phpmyadmin")
    @Primary
    public DataSource dataSource() throws Exception{
        Properties props = new Properties();

        DruidDataSource objDs = new DruidDataSource();
        
        props.put("driverClassName", _propsConfig.getProperty("jdbc.driverClassName"));
        props.put("url", _propsConfig.getProperty("jdbc.url"));
        props.put("username", _propsConfig.getProperty("jdbc.username"));
        props.put("password", _propsConfig.getProperty("jdbc.password"));
        props.put("initialSize", _propsConfig.getProperty("jdbc.initialSize"));
        props.put("minIdle", _propsConfig.getProperty("jdbc.minIdle"));
        props.put("maxActive", _propsConfig.getProperty("jdbc.maxActive"));
        props.put("maxWait", _propsConfig.getProperty("jdbc.maxWait"));
        props.put("timeBetweenEvictionRunsMillis", _propsConfig.getProperty("jdbc.timeBetweenEvictionRunsMillis"));
        props.put("minEvictableIdleTimeMillis", _propsConfig.getProperty("jdbc.minEvictableIdleTimeMillis"));
        props.put("maxPoolPreparedStatementPerConnectionSize", _propsConfig.getProperty("jdbc.maxPoolPreparedStatementPerConnectionSize"));
        props.put("filters", _propsConfig.getProperty("jdbc.filters"));
        
        objDs.setUrl(props.getProperty("url"));
        objDs.setDriverClassName(props.getProperty("driverClassName"));
        objDs.setUsername(props.getProperty("username"));
        objDs.setPassword(props.getProperty("password"));
        objDs.setInitialSize(Integer.valueOf(props.getProperty("initialSize")));
        objDs.setMinIdle(Integer.valueOf(props.getProperty("maxActive")));
        objDs.setMaxWait(Long.valueOf(props.getProperty("maxWait")));
        objDs.setMaxActive(Integer.valueOf(props.getProperty("maxActive")));
        objDs.setMinEvictableIdleTimeMillis(Long.valueOf(props.getProperty("minEvictableIdleTimeMillis")));

        try {
        	objDs.setFilters(props.getProperty("filters"));
        } catch (Exception e) {
            e.printStackTrace();
        }       
        
        return objDs;
    }

    @Bean(name = "sqlSessionFactory_mysql_phpmyadmin")
    @Primary
    //@ConditionalOnMissingBean 
    public SqlSessionFactory sqlSessionFactory(@Qualifier("dataSource_mysql_phpmyadmin") DataSource dataSource_mysql_phpmyadmin) throws Exception{
    	try {  
            SqlSessionFactoryBean sessionFactory = new SqlSessionFactoryBean();  
            sessionFactory.setDataSource(dataSource_mysql_phpmyadmin);  
            sessionFactory.setConfigLocation(new PathMatchingResourcePatternResolver().getResources(_propsConfig.getProperty("mybatis.configLocation"))[0]);
            sessionFactory.setTypeAliasesPackage(_propsConfig.getProperty("mybatis.typeAliasesPackage"));  
            sessionFactory.setMapperLocations(new PathMatchingResourcePatternResolver().getResources(_propsConfig.getProperty("mybatis.mapperLocations")));
            
            return sessionFactory.getObject(); 
        } catch (Exception e) {  
            return null;  
        }  
    }
    
    @Bean(name="sqlSessionTemplate_mysql_phpmyadmin")
    @Primary
    public SqlSessionTemplate sqlSessionTemplate(@Qualifier("sqlSessionFactory_mysql_phpmyadmin") SqlSessionFactory sqlSessionFactory_mysql_phpmyadmin) {
    	SqlSessionTemplate obj = new SqlSessionTemplate(sqlSessionFactory_mysql_phpmyadmin);
        return obj;
    }
    
	@Bean(name="mapperScanner_mysql_phpmyadmin")
	@Primary
    @DependsOn({"sqlSessionFactory_mysql_phpmyadmin", "sqlSessionTemplate_mysql_phpmyadmin"})
    public MapperScannerConfigurer mapperScannerConfigurer() {
        MapperScannerConfigurer obj = new MapperScannerConfigurer();
        obj.setBasePackage("com.zcn.swc.domain.phpmyadmin.mapper");
        obj.setSqlSessionFactoryBeanName("sqlSessionFactory_mysql_phpmyadmin");
        obj.setSqlSessionTemplateBeanName("sqlSessionTemplate_mysql_phpmyadmin");
        obj.setBeanName("mapperScanner_mysql_phpmyadmin");
        return obj;
    }

    @Bean(name="transactionManager_mysql_phpmyadmin")
    public DataSourceTransactionManager transactionManager(@Qualifier("dataSource_mysql_phpmyadmin") DataSource dataSource_mysql_phpmyadmin) {
      return new DataSourceTransactionManager(dataSource_mysql_phpmyadmin);
    }

}

// MyBatis_Sql2v5_testdb_Config


package com.zcn.swc.common;

import java.io.IOException;
import java.util.Properties;

import javax.sql.DataSource;

import org.apache.ibatis.session.SqlSessionFactory;
import org.mybatis.spring.SqlSessionFactoryBean;
import org.mybatis.spring.SqlSessionTemplate;
import org.mybatis.spring.mapper.MapperScannerConfigurer;
import org.springframework.beans.factory.annotation.Qualifier;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.context.annotation.DependsOn;
import org.springframework.core.io.support.PathMatchingResourcePatternResolver;
import org.springframework.jdbc.datasource.DataSourceTransactionManager;

import com.alibaba.druid.pool.DruidDataSource;


@Configuration    
public class MyBatis_Sql2v5_testdb_Config { 
	
	Properties _propsConfig = new Properties();
	
	public MyBatis_Sql2v5_testdb_Config() {
		// TODO Auto-generated constructor stub
        
        String filename = "mb/mb-sql2v5-testdb.properties";  
        try {
			_propsConfig.load(MyBatis_Sql2v5_testdb_Config.class.getClassLoader().getResourceAsStream(filename));
		} catch (IOException e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
		}          
	}
	
    @Bean(name = "dataSource_sql2v5_testdb")
    public DataSource dataSource() throws Exception{
        Properties props = new Properties();

        DruidDataSource objDs = new DruidDataSource();
        
        props.put("driverClassName", _propsConfig.getProperty("jdbc.driverClassName"));
        props.put("url", _propsConfig.getProperty("jdbc.url"));
        props.put("username", _propsConfig.getProperty("jdbc.username"));
        props.put("password", _propsConfig.getProperty("jdbc.password"));
        props.put("initialSize", _propsConfig.getProperty("jdbc.initialSize"));
        props.put("minIdle", _propsConfig.getProperty("jdbc.minIdle"));
        props.put("maxActive", _propsConfig.getProperty("jdbc.maxActive"));
        props.put("maxWait", _propsConfig.getProperty("jdbc.maxWait"));
        props.put("timeBetweenEvictionRunsMillis", _propsConfig.getProperty("jdbc.timeBetweenEvictionRunsMillis"));
        props.put("minEvictableIdleTimeMillis", _propsConfig.getProperty("jdbc.minEvictableIdleTimeMillis"));
        props.put("maxPoolPreparedStatementPerConnectionSize", _propsConfig.getProperty("jdbc.maxPoolPreparedStatementPerConnectionSize"));
        props.put("filters", _propsConfig.getProperty("jdbc.filters"));
        
        objDs.setUrl(props.getProperty("url"));
        objDs.setDriverClassName(props.getProperty("driverClassName"));
        objDs.setUsername(props.getProperty("username"));
        objDs.setPassword(props.getProperty("password"));
        objDs.setInitialSize(Integer.valueOf(props.getProperty("initialSize")));
        objDs.setMinIdle(Integer.valueOf(props.getProperty("maxActive")));
        objDs.setMaxWait(Long.valueOf(props.getProperty("maxWait")));
        objDs.setMaxActive(Integer.valueOf(props.getProperty("maxActive")));
        objDs.setMinEvictableIdleTimeMillis(Long.valueOf(props.getProperty("minEvictableIdleTimeMillis")));

        try {
        	objDs.setFilters(props.getProperty("filters"));
        } catch (Exception e) {
            e.printStackTrace();
        }       
        
        return objDs;
    }

    @Bean(name = "sqlSessionFactory_sql2v5_testdb")
    public SqlSessionFactory sqlSessionFactory(@Qualifier("dataSource_sql2v5_testdb") DataSource dataSource_sql2v5_testdb) throws Exception{
    	try {  
            SqlSessionFactoryBean sessionFactory = new SqlSessionFactoryBean();  
            sessionFactory.setDataSource(dataSource_sql2v5_testdb);  
            sessionFactory.setConfigLocation(new PathMatchingResourcePatternResolver().getResources(_propsConfig.getProperty("mybatis.configLocation"))[0]);
            sessionFactory.setTypeAliasesPackage(_propsConfig.getProperty("mybatis.typeAliasesPackage"));  
            sessionFactory.setMapperLocations(new PathMatchingResourcePatternResolver().getResources(_propsConfig.getProperty("mybatis.mapperLocations")));
            
            return sessionFactory.getObject(); 
        } catch (Exception e) {  
            return null;  
        }  
    }
    
    @Bean(name="sqlSessionTemplate_sql2v5_testdb")
    public SqlSessionTemplate sqlSessionTemplate(@Qualifier("sqlSessionFactory_sql2v5_testdb") SqlSessionFactory sqlSessionFactory_sql2v5_testdb) {
    	SqlSessionTemplate obj = new SqlSessionTemplate(sqlSessionFactory_sql2v5_testdb);
        return obj;
    }
    
	@Bean(name="mapperScanner_sql2v5_testdb")
    @DependsOn({"sqlSessionFactory_sql2v5_testdb", "sqlSessionTemplate_sql2v5_testdb"})
    public MapperScannerConfigurer mapperScannerConfigurer() {
        MapperScannerConfigurer obj = new MapperScannerConfigurer();
        obj.setBasePackage("com.zcn.swc.domain.testdb.mapper");
        obj.setSqlSessionFactoryBeanName("sqlSessionFactory_sql2v5_testdb");
        obj.setSqlSessionTemplateBeanName("sqlSessionTemplate_sql2v5_testdb");
        obj.setBeanName("mapperScanner_sql2v5_testdb");
        return obj;
    }

    @Bean(name="transactionManager_sql2v5_testdb")
    public DataSourceTransactionManager transactionManager(@Qualifier("dataSource_sql2v5_testdb") DataSource dataSource_sql2v5_testdb) {
      return new DataSourceTransactionManager(dataSource_sql2v5_testdb);
    }

}

// MyBatis_Sql2v5_testdb02_Config


package com.zcn.swc.common;

import java.io.IOException;
import java.util.Properties;

import javax.sql.DataSource;

import org.apache.ibatis.session.SqlSessionFactory;
import org.mybatis.spring.SqlSessionFactoryBean;
import org.mybatis.spring.SqlSessionTemplate;
import org.mybatis.spring.mapper.MapperScannerConfigurer;
import org.springframework.beans.factory.annotation.Qualifier;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.context.annotation.DependsOn;
import org.springframework.core.io.support.PathMatchingResourcePatternResolver;
import org.springframework.jdbc.datasource.DataSourceTransactionManager;

import com.alibaba.druid.pool.DruidDataSource;


@Configuration    
public class MyBatis_Sql2v5_testdb02_Config { 
	
	Properties _propsConfig = new Properties();
	
	public MyBatis_Sql2v5_testdb02_Config() {
		// TODO Auto-generated constructor stub
        
        String filename = "mb/mb-sql2v5-testdb02.properties";  
        try {
			_propsConfig.load(MyBatis_Sql2v5_testdb02_Config.class.getClassLoader().getResourceAsStream(filename));
		} catch (IOException e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
		}          
	}
	
    @Bean(name = "dataSource_sql2v5_testdb02")
    public DataSource dataSource() throws Exception{
        Properties props = new Properties();

        DruidDataSource objDs = new DruidDataSource();
        
        props.put("driverClassName", _propsConfig.getProperty("jdbc.driverClassName"));
        props.put("url", _propsConfig.getProperty("jdbc.url"));
        props.put("username", _propsConfig.getProperty("jdbc.username"));
        props.put("password", _propsConfig.getProperty("jdbc.password"));
        props.put("initialSize", _propsConfig.getProperty("jdbc.initialSize"));
        props.put("minIdle", _propsConfig.getProperty("jdbc.minIdle"));
        props.put("maxActive", _propsConfig.getProperty("jdbc.maxActive"));
        props.put("maxWait", _propsConfig.getProperty("jdbc.maxWait"));
        props.put("timeBetweenEvictionRunsMillis", _propsConfig.getProperty("jdbc.timeBetweenEvictionRunsMillis"));
        props.put("minEvictableIdleTimeMillis", _propsConfig.getProperty("jdbc.minEvictableIdleTimeMillis"));
        props.put("maxPoolPreparedStatementPerConnectionSize", _propsConfig.getProperty("jdbc.maxPoolPreparedStatementPerConnectionSize"));
        props.put("filters", _propsConfig.getProperty("jdbc.filters"));
        
        objDs.setUrl(props.getProperty("url"));
        objDs.setDriverClassName(props.getProperty("driverClassName"));
        objDs.setUsername(props.getProperty("username"));
        objDs.setPassword(props.getProperty("password"));
        objDs.setInitialSize(Integer.valueOf(props.getProperty("initialSize")));
        objDs.setMinIdle(Integer.valueOf(props.getProperty("maxActive")));
        objDs.setMaxWait(Long.valueOf(props.getProperty("maxWait")));
        objDs.setMaxActive(Integer.valueOf(props.getProperty("maxActive")));
        objDs.setMinEvictableIdleTimeMillis(Long.valueOf(props.getProperty("minEvictableIdleTimeMillis")));

        try {
        	objDs.setFilters(props.getProperty("filters"));
        } catch (Exception e) {
            e.printStackTrace();
        }       
        
        return objDs;
    }

    @Bean(name = "sqlSessionFactory_sql2v5_testdb02")
    public SqlSessionFactory sqlSessionFactory(@Qualifier("dataSource_sql2v5_testdb02") DataSource dataSource_sql2v5_testdb02) throws Exception{
    	try {  
            SqlSessionFactoryBean sessionFactory = new SqlSessionFactoryBean();  
            sessionFactory.setDataSource(dataSource_sql2v5_testdb02);  
            sessionFactory.setConfigLocation(new PathMatchingResourcePatternResolver().getResources(_propsConfig.getProperty("mybatis.configLocation"))[0]);
            sessionFactory.setTypeAliasesPackage(_propsConfig.getProperty("mybatis.typeAliasesPackage"));  
            sessionFactory.setMapperLocations(new PathMatchingResourcePatternResolver().getResources(_propsConfig.getProperty("mybatis.mapperLocations")));
            
            return sessionFactory.getObject(); 
        } catch (Exception e) {  
            return null;  
        }  
    }
    
    @Bean(name="sqlSessionTemplate_sql2v5_testdb02")
    public SqlSessionTemplate sqlSessionTemplate(@Qualifier("sqlSessionFactory_sql2v5_testdb02") SqlSessionFactory sqlSessionFactory_sql2v5_testdb02) {
    	SqlSessionTemplate obj = new SqlSessionTemplate(sqlSessionFactory_sql2v5_testdb02);
        return obj;
    }
    
	@Bean(name="mapperScanner_sql2v5_testdb02")
    @DependsOn({"sqlSessionFactory_sql2v5_testdb02", "sqlSessionTemplate_sql2v5_testdb02"})
    public MapperScannerConfigurer mapperScannerConfigurer() {
        MapperScannerConfigurer obj = new MapperScannerConfigurer();
        obj.setBasePackage("com.zcn.swc.domain.testdb02.mapper");
        obj.setSqlSessionFactoryBeanName("sqlSessionFactory_sql2v5_testdb02");
        obj.setSqlSessionTemplateBeanName("sqlSessionTemplate_sql2v5_testdb02");
        obj.setBeanName("mapperScanner_sql2v5_testdb02");
        return obj;
    }

    @Bean(name="transactionManager_sql2v5_testdb02")
    public DataSourceTransactionManager transactionManager(@Qualifier("dataSource_sql2v5_testdb02") DataSource dataSource_sql2v5_testdb02) {
      return new DataSourceTransactionManager(dataSource_sql2v5_testdb02);
    }

}


6、测试

一、com.zcn.swc.domain.phpmyadmin包下建立一个servier包,在其下新建一个类:PmaUserconfigService,代码如下:

package com.zcn.swc.domain.phpmyadmin.service;

import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;

import com.zcn.swc.domain.phpmyadmin.mapper.phpmyadmin.MPma_userconfigMapper;
import com.zcn.swc.domain.phpmyadmin.model.phpmyadmin.MPma_userconfig;

@Service
public class PmaUserconfigService {
	
	@Autowired
	private MPma_userconfigMapper mPma_userconfigMapper;
	
	public MPma_userconfig getUserconfig(String strUsername) {
		return this.mPma_userconfigMapper.selectByPrimaryKey(strUsername);
	}
}

二、com.zcn.swc.domain.testdb包下建立一个servier包,在其下新建一个类:MemberService,代码如下:

package com.zcn.swc.domain.testdb.service;

import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;

import com.zcn.swc.domain.testdb.mapper.testdb.dbo.MCom_memberMapper;
import com.zcn.swc.domain.testdb.model.testdb.dbo.MCom_member;

@Service("testdbMemberService")
public class MemberService {
	@Autowired
	private MCom_memberMapper mCom_memberMapper;
	
	public MCom_member getMember(String strId) {
		return this.mCom_memberMapper.selectByPrimaryKey(strId);
	}
}

三、com.zcn.swc.domain.testdb02包下建立一个servier包,在其下新建一个类:MemberService,代码如下(注意此步中的mapper成员使用了@Qualifier注解):

package com.zcn.swc.domain.testdb02.service;


import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Qualifier;
import org.springframework.stereotype.Service;

import com.zcn.swc.domain.testdb02.mapper.testdb02.dbo.MCom_memberMapper;
import com.zcn.swc.domain.testdb02.model.testdb02.dbo.MCom_member;


@Service("testdb02MemberService")
public class MemberService {

	@Autowired
	@Qualifier("MCom_memberMapper02_test")
	private MCom_memberMapper mCom_memberMapper;
	
	public MCom_member getMember(String strId) {
		return this.mCom_memberMapper.selectByPrimaryKey(strId);
	}
}

四、在com.zcn.swc.domain.testdb02.mapper.testdb02.dbo.MCom_memberMapper接口定义前,添加@Named注解,如下:

package com.zcn.swc.domain.testdb02.mapper.testdb02.dbo;

import javax.inject.Named;

import com.zcn.swc.domain.testdb02.model.testdb02.dbo.MCom_member;

@Named("MCom_memberMapper02_test")
public interface MCom_memberMapper {
    int deleteByPrimaryKey(String id);

    int insert(MCom_member record);

    int insertSelective(MCom_member record);

    MCom_member selectByPrimaryKey(String id);

    int updateByPrimaryKeySelective(MCom_member record);

    int updateByPrimaryKey(MCom_member record);
}

五、在com.zcn.swc下新建一个包controller,在其中建立一个Controller类MemberController,代码如下:

package com.zcn.swc.controller;

import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Qualifier;
import org.springframework.stereotype.Controller;
import org.springframework.ui.Model;
import org.springframework.web.bind.annotation.RequestMapping;

import com.zcn.swc.domain.phpmyadmin.model.phpmyadmin.MPma_userconfig;
import com.zcn.swc.domain.phpmyadmin.service.PmaUserconfigService;


@Controller
public class MemberController {

	@Autowired
	private PmaUserconfigService pmaUserconfigService;
	
	@Autowired
	@Qualifier("testdbMemberService")
	private com.zcn.swc.domain.testdb.service.MemberService memberService;
	
	@Autowired
	@Qualifier("testdb02MemberService")
	private com.zcn.swc.domain.testdb02.service.MemberService memberService02;
	
	@RequestMapping(value="/getMember")
	public String getHyxxById(Model model) {
		String strRet = "member";
		
		// phpmyadmin info
		MPma_userconfig objRetMysqlPhpmyadmin = pmaUserconfigService.getUserconfig("root");
		
		// sql2v5 testdb member info
		String strId = "21223fc4-8140-4c2a-9a02-ae1c539fcc1f";
		com.zcn.swc.domain.testdb.model.testdb.dbo.MCom_member objRetTestDb = memberService.getMember(strId);
		
		// sql2v5 testdb02 member info
		String strId02 = "1ac7ed1e-2f73-4190-b48b-5fa122a8ba00";
		com.zcn.swc.domain.testdb02.model.testdb02.dbo.MCom_member objRetTestDb02 = memberService02.getMember(strId02);

		model.addAttribute("testdb", objRetTestDb);
		model.addAttribute("testdb02", objRetTestDb02);
		model.addAttribute("mysql", objRetMysqlPhpmyadmin);
		return strRet;
	} 
}


七、在/src/main/resources/templates下,新建一个member.html文件:




    Getting Started: Serving Web Content
    


    


八、在/src/main/resource/application.properties内添加如下配置(本步骤也可以省去,与url请求有关):

server.contextPath=/mbbase/

 

九、右键点击mbbase工程,在Run As内选择Spring Boot App,等待工程自动生成并打开内置tomcat;

十、打开浏览器,输入:http://localhost:8080/mbbase/getMember;

最终会看到三条结果。


7、附sql脚本:

//mysql-phpmyadmin

-- Database: phpmyadmin
CREATE TABLE `pma_userconfig` (
  `username` varchar(64) COLLATE utf8_bin NOT NULL,
  `timevalue` timestamp NOT NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP,
  `config_data` text COLLATE utf8_bin NOT NULL,
  PRIMARY KEY (`username`)
) ENGINE=MyISAM DEFAULT CHARSET=utf8 COLLATE=utf8_bin COMMENT='User preferences storage for phpMyAdmin';

INSERT INTO `pma_userconfig` VALUES ('root','2015-12-13 07:30:58','{\"lang\":\"zh_CN\"}');

// sql2v5-testdb

-- Database: testdb
CREATE TABLE [dbo].[com_member](
	[id] [uniqueidentifier] NOT NULL,
	[username] [varchar](64) NULL,
	[password] [varchar](64) NULL,
	[salt] [varchar](16) NULL,
	[email] [varchar](128) NULL,
	[membertype] [int] NULL,
	[lockstate] [int] NULL,
	[staffid] [uniqueidentifier] NULL,
	[begindate] [int] NULL DEFAULT ([dbo].[getIntCurrentDate]()),
	[enddate] [int] NULL,
	[flag] [int] NULL,
	[remark] [varchar](256) NULL,
	[createid] [uniqueidentifier] NULL,
	[createdate] [int] NULL DEFAULT ([dbo].[getIntCurrentDate]()),
	[createtime] [int] NULL DEFAULT ([dbo].[getIntCurrentTime]()),
	[updateid] [uniqueidentifier] NULL,
	[updatedate] [int] NULL,
	[updatetime] [int] NULL,
	[delid] [uniqueidentifier] NULL,
	[deldate] [int] NULL,
	[deltime] [int] NULL,
 CONSTRAINT [PK_COM_MEMBER] PRIMARY KEY CLUSTERED 
(
	[id] ASC
)WITH (PAD_INDEX  = OFF, STATISTICS_NORECOMPUTE  = OFF, IGNORE_DUP_KEY = OFF, ALLOW_ROW_LOCKS  = ON, ALLOW_PAGE_LOCKS  = ON) ON [PRIMARY]
) ON [PRIMARY]

insert into com_member(id, username, password, salt)  VALUES ('21223fc4-8140-4c2a-9a02-ae1c539fcc1f', 'system', 'R294c3a2XzOOrIjHZOSG9qSsnW6fVh2+', '123456');

// sql2v5-testdb02

-- Database: testdb02
CREATE TABLE [dbo].[com_member](
	[id] [uniqueidentifier] NOT NULL,
	[username] [varchar](64) NULL,
	[password] [varchar](64) NULL,
	[salt] [varchar](16) NULL,
	[email] [varchar](128) NULL,
	[membertype] [int] NULL,
	[lockstate] [int] NULL,
	[staffid] [uniqueidentifier] NULL,
	[begindate] [int] NULL DEFAULT ([dbo].[getIntCurrentDate]()),
	[enddate] [int] NULL,
	[flag] [int] NULL,
	[remark] [varchar](256) NULL,
	[createid] [uniqueidentifier] NULL,
	[createdate] [int] NULL DEFAULT ([dbo].[getIntCurrentDate]()),
	[createtime] [int] NULL DEFAULT ([dbo].[getIntCurrentTime]()),
	[updateid] [uniqueidentifier] NULL,
	[updatedate] [int] NULL,
	[updatetime] [int] NULL,
	[delid] [uniqueidentifier] NULL,
	[deldate] [int] NULL,
	[deltime] [int] NULL,
 CONSTRAINT [PK_COM_MEMBER] PRIMARY KEY CLUSTERED 
(
	[id] ASC
)WITH (PAD_INDEX  = OFF, STATISTICS_NORECOMPUTE  = OFF, IGNORE_DUP_KEY = OFF, ALLOW_ROW_LOCKS  = ON, ALLOW_PAGE_LOCKS  = ON) ON [PRIMARY]
) ON [PRIMARY]

insert into com_member(id, username, password, salt)  VALUES ('1ac7ed1e-2f73-4190-b48b-5fa122a8ba00', 'core02', 'MV8/+oYf8J4moKBhay4O6ObegzZxJrnt+', '123456');


8、参考或有用的链接

第五章 springboot + mybatis:http://www.cnblogs.com/java-zhao/p/5350021.html

Building theConnection URL:https://docs.microsoft.com/en-us/sql/connect/jdbc/building-the-connection-url

关于jdbc的数据库驱动类DriverManager.getConnection()参数:http://blog.sina.com.cn/s/blog_9653ee0f0101ji7s.html

Spring Boot -Environment @Autowired throws NullPointerExceptio:http://stackoverflow.com/questions/19454289/spring-boot-environment-autowired-throws-nullpointerexception

mybatis整合spring报java.lang.AbstractMethodError:org.mybatis.spring.transaction:http://blog.csdn.net/zljava2009/article/details/52092358

Spring BootMultiple Datasource:http://stackoverflow.com/questions/27614301/spring-boot-multiple-datasource

Spring Boot下配置MyBatis多数据源:http://blog.csdn.net/asdfsfsdgdfgh/article/details/51481911

[Java][MyBatis]mapperLocations属性通配符的使用:http://blog.csdn.net/szwangdf/article/details/23432783

mybatis-generator重新生成代码时的SQL映射文件覆盖:http://www.ithao123.cn/content-7476250.html

com.microsoft.sqlserver.jdbc.SQLServerException:对象名 ‘xxx' 无效:http://blog.csdn.net/pcdaan/article/details/6524472

数据库schema与catalog的理解:http://blog.csdn.net/nash603/article/details/40506713

MyBatisGenerator XML 配置参考:http://blog.csdn.net/gzg1001/article/details/51935948

Result Mapscollection already contains value for xxxMapper.BaseResultMap错误解决办法:http://blog.csdn.net/ldl22847/article/details/50390919

Spring Boot导入XML配置【从零开始学Spring Boot】:http://412887952-qq-com.iteye.com/blog/2293846

SSM:spring+springmvc+mybatis框架中的XML配置文件功能详细解释:http://blog.csdn.net/yijiemamin/article/details/51156189

Distributedtransactions with multiple databases, Spring Boot, Spring Data JPA and Atomikos:http://fabiomaffioletti.me/blog/2014/04/15/distributed-transactions-multiple-databases-spring-boot-spring-data-jpa-atomikos/

Spring中depends-on属性:http://chenfeng0104.iteye.com/blog/757875

javax.inject中@Inject、@Named、@Qualifier和@Provider用法:http://blog.csdn.net/binxigogo/article/details/7851924

MybatisMapperScannerConfigurer 自动扫描 将Mapper接口生成代理注入到Spring:http://www.cnblogs.com/daxin/p/3545040.html

 

9、工程下载: 工程下载

你可能感兴趣的:(java,sts,springboot,mybatis,多数据源)