1.新建springboot项目
2.修改application.yml 如下,有两个数据源jdbc 和jdbc2
#the first datasource jdbc: driverClassName: com.mysql.jdbc.Driver url: jdbc:mysql://localhost:3306/test1?useUnicode=true&charaterEncoding=utf-8 serverName: 127.0.0.1 username: root password: root #the second datasource jdbc2: driverClassName: com.mysql.jdbc.Driver url: jdbc:mysql://localhost:3306/test2?useUnicode=true&charaterEncoding=utf-8 serverName: 127.0.0.1 username: root password: root # SPRING PROFILES spring: # HTTP ENCODING http: encoding.charset: UTF-8 encoding.enable: true encoding.force: true # MyBatis mybatis: typeAliasesPackage: com.niezheng,datasource.entity mapperLocations: classpath:/mybatis/*Mapper.xml |
3.新建数据库枚举类型,数据库为test1 和test2
package com.niezheng.datasource.common; /** * @Author: niezheng * @Description: 列举数据源的key * @Date: Create in 12:18 2017/12/19 * @Modified By: */ public enum DataBaseType { test1,test2 } |
4.新建DatabaseContextHolder类
package com.niezheng.datasource.common; /** * @Author: niezheng * @Description: 作用:1、保存一个线程安全的DatabaseType容器 * 2.构建一个DatabaseType容器,并提供了向其中设置和获取DatabaseType的方法 * @Date: Create in 12:20 2017/12/19 * @Modified By: */ public class DatabaseContextHolder { private static final ThreadLocal<DataBaseType> contextHolder = new ThreadLocal<DataBaseType>() { @Override protected DataBaseType initialValue() { return DataBaseType.test1; } }; public static void setDatabaseType(DataBaseType type) { contextHolder.set(type); } public static DataBaseType getDatabaseType() { return contextHolder.get(); } } |
5.新建DynamicDataSource类
package com.niezheng.datasource.common; import org.springframework.jdbc.datasource.lookup.AbstractRoutingDataSource; /** * @Author: niezheng * @Description: 使用DatabaseContextHolder获取当前线程的DatabaseType * @Date: Create in 12:27 2017/12/19 * @Modified By: */ public class DynamicDataSource extends AbstractRoutingDataSource { @Override protected Object determineCurrentLookupKey() { return DatabaseContextHolder.getDatabaseType(); } } |
6.新建MyBatisConfig类
package com.niezheng.datasource.common; import com.alibaba.druid.pool.DruidDataSourceFactory; import org.apache.ibatis.session.SqlSessionFactory; import org.mybatis.spring.SqlSessionFactoryBean; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.beans.factory.annotation.Qualifier; import org.springframework.boot.autoconfigure.jdbc.DataSourceBuilder; import org.springframework.boot.context.properties.ConfigurationProperties; import org.springframework.context.annotation.Bean; import org.springframework.context.annotation.Configuration; import org.mybatis.spring.annotation.MapperScan; import org.springframework.context.annotation.Primary; import org.springframework.core.env.Environment; import org.springframework.core.io.support.PathMatchingResourcePatternResolver; import org.springframework.jdbc.datasource.DataSourceTransactionManager; import javax.sql.DataSource; import java.io.IOException; import java.util.HashMap; import java.util.Map; import java.util.Properties; /** * @Author: niezheng * @Description: * @Date: Create in 14:24 2017/12/19 * @Modified By: */ @Configuration @MapperScan(basePackages = "com.niezheng.datasource.mapper") public class MyBatisConfig { /** * 创建数据源 * @return * @throws Exception */ @Primary @Bean("test1DataSource") @ConfigurationProperties(prefix = "jdbc") public DataSource test1DataSource() throws Exception { return DataSourceBuilder.create().build(); } @Bean("test2DataSource") @ConfigurationProperties(prefix = "jdbc2") public DataSource test2DataSource() throws Exception { return DataSourceBuilder.create().build(); } /** * @Primary 该注解表示在同一个接口有多个实现类可以注入的时候,默认选择哪一个,热不是让@autowire报错 * @Qualifier 根据名称进行注入,通常是在具有相同的多个类型的实例的一个注入,(例如有多个DataSource类型的实例) * @param myTestDbDataSource * @param myTestDb2DataSource * @return */ @Bean public DynamicDataSource dataSource(@Qualifier("test1DataSource") DataSource myTestDbDataSource, @Qualifier("test2DataSource") DataSource myTestDb2DataSource){ Map<Object,Object> targetDataSource = new HashMap<>(); targetDataSource.put(DataBaseType.test1,myTestDbDataSource); targetDataSource.put(DataBaseType.test2,myTestDb2DataSource); DynamicDataSource dynamicDataSource = new DynamicDataSource(); dynamicDataSource.setTargetDataSources(targetDataSource); dynamicDataSource.setDefaultTargetDataSource(myTestDbDataSource); return dynamicDataSource; } /** * 根据数据源创建SqlSessionFactory * @param dynamicDataSource * @return * @throws Exception */ @Bean public SqlSessionFactory sqlSessionFactory(DynamicDataSource dynamicDataSource) throws Exception { SqlSessionFactoryBean sessionFactoryBean = new SqlSessionFactoryBean(); /**指定数据源(必须有否则报错)*/ sessionFactoryBean.setDataSource(dynamicDataSource); // 下边两句仅仅用于*.xml文件,如果整个持久层操作不需要使用到xml文件的话(只用注解就可以搞定),则不加 /* sessionFactoryBean.setTypeAliasesPackage(env.getProperty("mybatis.typeAliasesPackage")); sessionFactoryBean.setMapperLocations(new PathMatchingResourcePatternResolver().getResources(env.getProperty("mybatis.mapperLocations")));*/ return sessionFactoryBean.getObject(); } /** * 配置事务管理器 * @param dynamicDataSource * @return */ @Bean public DataSourceTransactionManager transactionManager(DynamicDataSource dynamicDataSource){ return new DataSourceTransactionManager(dynamicDataSource); } } |
7.使用AOP动态切换数据源
package com.niezheng.datasource.Aspect; import com.niezheng.datasource.common.DataBaseType; import com.niezheng.datasource.common.DatabaseContextHolder; import com.niezheng.datasource.dao.ShopDao; import org.aspectj.lang.JoinPoint; import org.aspectj.lang.annotation.Aspect; import org.aspectj.lang.annotation.Before; import org.aspectj.lang.annotation.Pointcut; import org.springframework.stereotype.Component; /** * @Author: niezheng * @Description: * @Date: Create in 16:04 2017/12/19 * @Modified By: */ @Aspect @Component public class DataSourceAspect { /** * 使用空方法定义切点表达式 */ @Pointcut("execution(* com.niezheng.datasource.dao.*.*(..))") public void declareJointPointExpression() { } @Before("declareJointPointExpression()") public void setDataSourceKey(JoinPoint point){ if(point.getTarget() instanceof ShopDao){ DatabaseContextHolder.setDatabaseType(DataBaseType.test1); }else { DatabaseContextHolder.setDatabaseType(DataBaseType.test2); } } } |
8.新建test1库 和test2库查询
package com.niezheng.datasource.mapper; import com.niezheng.datasource.entity.Person; import com.niezheng.datasource.entity.Shop; import org.apache.ibatis.annotations.Param; import org.apache.ibatis.annotations.Result; import org.apache.ibatis.annotations.Results; import org.apache.ibatis.annotations.Select; /** * @Author: niezheng * @Description: * @Date: Create in 17:02 2017/12/19 * @Modified By: */ public interface PersonMapper { @Select("SELECT * FROM t_person WHERE id = #{id}") @Results(value = { @Result(id = true, column = "id", property = "id"), @Result(column = "person_name", property = "personName") }) public Person getPerson(@Param("id") int id); } |
package com.niezheng.datasource.mapper; import com.niezheng.datasource.entity.Shop; import org.apache.ibatis.annotations.Param; import org.apache.ibatis.annotations.Result; import org.apache.ibatis.annotations.Results; import org.apache.ibatis.annotations.Select; /** * @Author: niezheng * @Description: * @Date: Create in 15:40 2017/12/19 * @Modified By: */ public interface ShopMapper { @Select("SELECT * FROM t_shop WHERE id = #{id}") @Results(value = { @Result(id = true, column = "id", property = "id"), @Result(column = "shop_name", property = "shopName") }) public Shop getShop(@Param("id") int id); } |
9.新建controller层进行访问
package com.niezheng.datasource.controller; import com.niezheng.datasource.entity.Person; import com.niezheng.datasource.entity.Shop; import com.niezheng.datasource.service.PersonService; import com.niezheng.datasource.service.ShopService; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.web.bind.annotation.RequestMapping; import org.springframework.web.bind.annotation.RestController; /** * @Author: niezheng * @Description: * @Date: Create in 16:17 2017/12/19 * @Modified By: */ @RestController @RequestMapping("datasource") public class ShopController { @Autowired private ShopService shopService; @Autowired private PersonService personService; @RequestMapping("/shop") public Shop getShop(){ Shop shop = shopService.getShop(1); return shop; } @RequestMapping("/person") public Person getPerson(){ Person person = personService.getPerson(1); return person; } } |
10.新建数据库test1 和test2
11.启动项目浏览器访问