1.使用spring+mybatis构建多数据源
1.1项目环境:spring+mybatis+mysql 依赖如下 依赖注释部分开启后 可以作为SSM项目使用,下图只为测试多数据源
<properties>
<project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
<maven.compiler.source>1.7</maven.compiler.source>
<maven.compiler.target>1.7</maven.compiler.target>
<spring.version>4.3.7.RELEASE</spring.version>
<slf4j.version>1.6.6</slf4j.version>
<log4j.version>1.2.12</log4j.version>
<mysql.version>5.1.6</mysql.version>
<mybatis.version>3.4.5</mybatis.version>
</properties>
<dependencies>
<!-- spring -->
<dependency>
<groupId>org.aspectj</groupId>
<artifactId>aspectjweaver</artifactId>
<version>1.6.8</version>
</dependency>
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-aop</artifactId>
<version>${spring.version}</version>
</dependency>
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-context</artifactId>
<version>${spring.version}</version>
</dependency>
<!-- <dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-web</artifactId>
<version>${spring.version}</version>
</dependency>
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-webmvc</artifactId>
<version>${spring.version}</version>
</dependency>-->
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-test</artifactId>
<version>${spring.version}</version>
</dependency>
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-tx</artifactId>
<version>${spring.version}</version>
</dependency>
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-jdbc</artifactId>
<version>${spring.version}</version>
</dependency>
<dependency>
<groupId>junit</groupId>
<artifactId>junit</artifactId>
<version>4.12</version>
<scope>compile</scope>
</dependency>
<dependency>
<groupId>mysql</groupId>
<artifactId>mysql-connector-java</artifactId>
<version>${mysql.version}</version>
</dependency>
<!--
<dependency>
<groupId>javax.servlet</groupId>
<artifactId>servlet-api</artifactId>
<version>2.5</version>
</dependency>
<dependency>
<groupId>javax.servlet.jsp</groupId>
<artifactId>jsp-api</artifactId>
<version>2.0</version>
<scope>provided</scope>
</dependency>
-->
<!-- log start -->
<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>
<!-- log end -->
<!-- mybatis -->
<dependency>
<groupId>org.mybatis</groupId>
<artifactId>mybatis</artifactId>
<version>${mybatis.version}</version>
</dependency>
<dependency>
<groupId>org.mybatis</groupId>
<artifactId>mybatis-spring</artifactId>
<version>1.3.0</version>
</dependency>
<dependency>
<groupId>c3p0</groupId>
<artifactId>c3p0</artifactId>
<version>0.9.1.2</version>
<type>jar</type>
<scope>compile</scope>
</dependency>
<!--工具类-->
<!-- https://mvnrepository.com/artifact/org.apache.commons/commons-lang3 -->
<dependency>
<groupId>org.apache.commons</groupId>
<artifactId>commons-lang3</artifactId>
<version>3.8.1</version>
</dependency>
<dependency>
<groupId>com.alibaba</groupId>
<artifactId>fastjson</artifactId>
<version>1.2.66</version>
</dependency>
<!--lombok-->
<dependency>
<groupId>org.projectlombok</groupId>
<artifactId>lombok</artifactId>
<version>1.18.0</version>
</dependency>
<!--代码生成器-->
<dependency>
<groupId>org.mybatis.generator</groupId>
<artifactId>mybatis-generator-core</artifactId>
<version>1.3.7</version>
</dependency>
<!-- <!–文件上传–>
<dependency>
<groupId>commons-fileupload</groupId>
<artifactId>commons-fileupload</artifactId>
<version>1.3.1</version>
</dependency>
<dependency>
<groupId>commons-io</groupId>
<artifactId>commons-io</artifactId>
<version>2.5</version>S
</dependency>
<!–定时任务整合–>
<dependency>
<groupId>org.quartz-scheduler</groupId>
<artifactId>quartz</artifactId>
<version>2.3.1</version>
</dependency>
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-context-support</artifactId>
<version>${spring.version}</version>
</dependency>-->
</dependencies>
<build>
<plugins>
<plugin>
<groupId>org.mybatis.generator</groupId>
<artifactId>mybatis-generator-maven-plugin</artifactId>
<version>1.3.2</version>
<configuration>
<verbose>true</verbose>
<overwrite>true</overwrite>
</configuration>
</plugin>
</plugins>
</build>
####2 配置文件
在resource下建立这样的目录,其中:
spring-com:spring配置
spring-db:spring整合Mybatis
sqlMapConfig.xml:mybatis总配置文件,也可以不写直接用spring整合
generatorConfig.xml:mybatis代码生成器
log4j.properties.xml: 日志打印设置
spring.xml: 引用上面的两个spring文件
system.properties:数据库配置等
代码如下:
spring-com
<?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.xsd
http://www.springframework.org/schema/context
http://www.springframework.org/schema/context/spring-context.xsd
http://www.springframework.org/schema/aop
http://www.springframework.org/schema/aop/spring-aop.xsd">
<!--注解扫描 -->
<context:component-scan base-package="com.*">
<!--配置哪些注解不扫描-->
<context:exclude-filter type="annotation" expression="org.springframework.stereotype.Controller" />
</context:component-scan>
<aop:aspectj-autoproxy/>
</beans>
spring-db.xml
<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xmlns:aop="http://www.springframework.org/schema/aop"
xmlns:context="http://www.springframework.org/schema/context"
xsi:schemaLocation="http://www.springframework.org/schema/beans
http://www.springframework.org/schema/beans/spring-beans.xsd
http://www.springframework.org/schema/aop
http://www.springframework.org/schema/aop/spring-aop.xsd
http://www.springframework.org/schema/context
http://www.springframework.org/schema/context/spring-context.xsd">
<!--mybatis -->
<context:property-placeholder location="classpath:system.properties"/>
<!--会见数据源-->
<bean id="dataSource1" class="com.mchange.v2.c3p0.ComboPooledDataSource">
<property name="driverClass" value="${jdbc.driver}"></property>
<property name="jdbcUrl" value="${jdbc.url}"></property>
<property name="user" value="${jdbc.username}"></property>
<property name="password" value="${jdbc.password}"></property>
</bean>
<!--电话数据源-->
<bean id="dataSource2" class="com.mchange.v2.c3p0.ComboPooledDataSource">
<property name="driverClass" value="${jdbc.driver2}"></property>
<property name="jdbcUrl" value="${jdbc.url2}"></property>
<property name="user" value="${jdbc.username2}"></property>
<property name="password" value="${jdbc.password2}"></property>
</bean>
<!--数据源管理-->
<bean id="multipleDataSource" class="com.datasource.MultipleDataSource">
<property name="defaultTargetDataSource" ref="dataSource1"/>
<property name="targetDataSources">
<map>
<entry key="xwl" value-ref="dataSource1"/>
<entry key="zzz" value-ref="dataSource2"/>
</map>
</property>
</bean>
<!--sqlsessionfactory 改为数据源管理-->
<bean class="org.mybatis.spring.SqlSessionFactoryBean" id="sqlSessionFactory">
<property name="dataSource" ref="multipleDataSource"></property>
<property name="configLocation" value="classpath:spring/SqlMapConfig.xml"></property>
</bean>
<!--mapper-->
<bean class="org.mybatis.spring.mapper.MapperScannerConfigurer">
<property name="basePackage" value="com.*.dao"></property>
<property name="sqlSessionFactoryBeanName" value="sqlSessionFactory"></property>
</bean>
</beans>
注意MultipleDataSource这个bean,他是我们使用多数据源的关键,当我们在Map中输入对应的Key时,他就会调用对应的数据源
SqlMapConfig.xml
<?xml version="1.0" encoding="UTF-8" ?>
<!DOCTYPE configuration
PUBLIC "-//mybatis.org//DTD Config 3.0//EN"
"http://mybatis.org/dtd/mybatis-3-config.dtd">
<configuration>
<typeAliases>
<package name="com.*.po"/>
</typeAliases>
</configuration>
generatorConfig.xml
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE generatorConfiguration PUBLIC "-//mybatis.org//DTD MyBatis Generator Configuration 1.0//EN" "http://mybatis.org/dtd/mybatis-generator-config_1_0.dtd">
<generatorConfiguration>
<!-- <properties resource="mybatis.properties" />
-->
<classPathEntry location="E:\Maven\repository\mysql\mysql-connector-java\5.1.6\mysql-connector-java-5.1.6.jar" />
<context id="msqlTables" targetRuntime="MyBatis3">
<plugin type="org.mybatis.generator.plugins.SerializablePlugin"></plugin>
<!-- 为了防止生成的代码中有很多注释,比较难看,加入下面的配置控制 -->
<!-- <!– 是否去除自动生成的注释 true:是 : false:否 –> -->
<commentGenerator>
<property name="suppressDate" value="true"/>
<property name="suppressAllComments" value="true"/>
</commentGenerator>
<jdbcConnection connectionURL="jdbc:mysql://localhost:3306/library"
driverClass="com.mysql.jdbc.Driver" password="123" userId="root" >
<property name="nullCatalogMeansCurrent" value="true"/>
</jdbcConnection>
<javaTypeResolver>
<property name="forceBigDecimals" value="false" />
</javaTypeResolver>
<javaModelGenerator targetPackage="com.zzz.po" targetProject="F:\SpringBoot\ssm_data\src\main\java">
<property name="enableSubPackages" value="true"/>
<!-- 从数据库返回的值被清理前后的空格 -->
<property name="trimStrings" value="true" />
</javaModelGenerator>
<sqlMapGenerator targetPackage="com.zzz.dao" targetProject="F:\SpringBoot\ssm_data\src\main\resources">
<property name="enableSubPackages" value="true"/>
</sqlMapGenerator>
<javaClientGenerator type="XMLMAPPER" targetPackage="com.zzz.dao" targetProject="F:\SpringBoot\ssm_data\src\main\java">
<property name="enableSubPackages" value="true"/>
</javaClientGenerator>
<table tableName="admin" domainObjectName="Admin"
enableCountByExample="false" enableUpdateByExample="false" enableDeleteByExample="false"
enableSelectByExample="false" selectByExampleQueryId="false" >
<property name="useActualColumnNames" value="false"/>
</table>
</context>
</generatorConfiguration>
log4j.properties
#设置打印级别
log4j.rootCategory=INFO, CONSOLE, LOGFILE
# 输出到控制台
log4j.appender.CONSOLE=org.apache.log4j.ConsoleAppender
log4j.appender.CONSOLE.layout=org.apache.log4j.PatternLayout
log4j.appender.CONSOLE.layout.ConversionPattern=%d{ISO8601} %-6r [%15.15t] %-5p %30.30c %x - %m\n
# 输出到文件
log4j.appender.LOGFILE=org.apache.log4j.FileAppender
log4j.appender.LOGFILE.File=${catalina.base}/logs/synData/datacenter.log
log4j.appender.LOGFILE.Append=true
log4j.appender.LOGFILE.layout=org.apache.log4j.PatternLayout
log4j.appender.LOGFILE.layout.ConversionPattern=%d{ISO8601} %-6r [%15.15t] %-5p %30.30c %x - %m\n
spring.xml
<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xmlns:context="http://www.springframework.org/schema/context"
xsi:schemaLocation="http://www.springframework.org/schema/beans
http://www.springframework.org/schema/beans/spring-beans.xsd
http://www.springframework.org/schema/context
http://www.springframework.org/schema/context/spring-context.xsd" default-lazy-init="false">
<import resource="classpath:spring/spring-com.xml"/>
<import resource="classpath:spring/spring-db.xml"/>
</beans>
system.properties
#本地数据库配置-ivms
jdbc.driver=com.mysql.jdbc.Driver
jdbc.url=jdbc:mysql://localhost:3306/springboot?useUnicode=true&characterEncoding=utf8&allowMultiQueries=true
jdbc.username=root
jdbc.password=123
#本地数据库配置-swph
jdbc.driver2=com.mysql.jdbc.Driver
jdbc.url2=jdbc:mysql://localhost:3306/library?useUnicode=true&characterEncoding=utf8&allowMultiQueries=true
jdbc.username2=root
jdbc.password2=123
####3.创建基本的dao和po
根据目录,我的设计是当我们使用com.xwl包下的dao时,使用数据源1;当我们使用com.zzz目录下的dao访问数据库时,使用数据源2。至于怎么实现,通过MultipleDataSource这个bean,我们有两种方式,第一种,每次调用直接手动设置数据源,这意味着我们每次调用service或者dao之前,都要去调用一遍设置的方法,所以我们使用第二种方法,aop。
#####先建立对应MultipleDataSource的类
package com.datasource;
import org.springframework.jdbc.datasource.lookup.AbstractRoutingDataSource;
/**
* xwl 多数据源
*/
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();
}
}
就这样,当我们需要手动调用数据源的时候只需要调用 MultipleDataSource.setDataSourceKey("xwl")l即可,注意这个key是我们在spring-db中配置的。
#####这样我们手动的方式就建立完毕了,接下来我自己写了一个AOP的类来自动判断路径来选择数据源,
package com.datasource;
import org.aspectj.lang.ProceedingJoinPoint;
import org.aspectj.lang.annotation.Around;
import org.aspectj.lang.annotation.Aspect;
import org.springframework.stereotype.Component;
@Component
@Aspect
public class Data {
@Around("execution(* com.xwl.dao.*.*(..))")
public Object run1(ProceedingJoinPoint joinPoint) throws Throwable {
MultipleDataSource.setDataSourceKey("xwl");
return joinPoint.proceed();
}
@Around("execution(* com.zzz.dao.*.*(..))")
public Object run2(ProceedingJoinPoint joinPoint) throws Throwable {
MultipleDataSource.setDataSourceKey("zzz");
return joinPoint.proceed();
}
}
这里用了@Around标签其实有点不妥,应该使用@Before,当程序检测到我们方法的目录为com.zzz.dao时会调用zzz数据源,而无需我们手动调用。
测试
import com.xwl.dao.UserMapper;
import com.xwl.po.User;
import com.xwl.service.UserService;
import com.zzz.dao.AdminMapper;
import com.zzz.po.Admin;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.test.context.ContextConfiguration;
import org.springframework.test.context.junit4.SpringRunner;
/**
* @author xwl
* @program:
* @description:
* @date 2021-10-05 20:22:50
*/
@RunWith(SpringRunner.class)
@ContextConfiguration(value = "classpath:spring.xml")
public class demo {
@Autowired
public AdminMapper adminMapper;
@Autowired
public UserMapper userMapper;
@Test
public void test(){
Admin admin = adminMapper.selectByPrimaryKey(4);
System.out.println(admin.getUsername());
User user = userMapper.selectByPrimaryKey(35);
System.out.println(user.getUserName());
}
}
结果:
成功 OK
提示:我的dao和xml都是自动生成的 就不给大家看了,毕竟ssm就是配置太多了,知道配置就可以自己琢磨了,我也是自己琢磨出来的