}
@Pointcut(“execution(* com.warm.system.service.db2….(…))”)
private void db2Aspect() {
}
@Before( “db1Aspect()” )
public void db1(JoinPoint joinPoint) {
log.info(“切换到db1 数据源…”);
setDataSource(joinPoint,DBTypeEnum.db1);
}
@Before(“db2Aspect()” )
public void db2 (JoinPoint joinPoint) {
log.info(“切换到db2 数据源…”);
setDataSource(joinPoint,DBTypeEnum.db2);
}
/**
• 添加注解方式,如果有注解优先注解,没有则按传过来的数据源配置
• @param joinPoint
• @param dbTypeEnum
*/
private void setDataSource(JoinPoint joinPoint, DBTypeEnum dbTypeEnum) {
MethodSignature methodSignature = (MethodSignature) joinPoint.getSignature();
DataSourceSwitch dataSourceSwitch = methodSignature.getMethod().getAnnotation(DataSourceSwitch.class);
if (Objects.isNull(dataSourceSwitch) || Objects.isNull(dataSourceSwitch.value())) {
DbContextHolder.setDbType(dbTypeEnum);
}else{
log.info(“根据注解来切换数据源,注解值为:”+dataSourceSwitch.value());
switch (dataSourceSwitch.value().getValue()) {
case “db1”:
DbContextHolder.setDbType(DBTypeEnum.db1);
break;
case “db2”:
DbContextHolder.setDbType(DBTypeEnum.db2);
break;
default:
DbContextHolder.setDbType(dbTypeEnum);
}
}
}
}
DbContextHolder
package com.warm.common;
/**
• @Author DGD
• @date 2018/2/7.
*/
public class DbContextHolder {
private static final ThreadLocal contextHolder = new ThreadLocal<>();
/**
• 设置数据源
• @param dbTypeEnum
*/
public static void setDbType(DBTypeEnum dbTypeEnum) {
contextHolder.set(dbTypeEnum.getValue());
}
/**
• 取得当前数据源
• @return
*/
public static String getDbType() {
return (String) contextHolder.get();
}
/**
• 清除上下文数据
*/
public static void clearDbType() {
contextHolder.remove();
}
}
DBTypeEnum
package com.warm.common;
/**
• @Author DGD
• @date 2018/2/7.
*/
public enum DBTypeEnum {
db1(“db1”), db2(“db2”);
private String value;
DBTypeEnum(String value) {
this.value = value;
}
public String getValue() {
return value;
}
}
DynamicDataSource
package com.warm.common;
import org.springframework.jdbc.datasource.lookup.AbstractRoutingDataSource;
/**
• @Author DGD
• @date 2018/2/7.
*/
public class DynamicDataSource extends AbstractRoutingDataSource {
/**
• 取得当前使用哪个数据源
• @return
*/
@Override
protected Object determineCurrentLookupKey() {
return DbContextHolder.getDbType();
}
}
MybatisPlusConfig
package com.warm.config.mybatis;
import com.alibaba.druid.spring.boot.autoconfigure.DruidDataSourceBuilder;
import com.baomidou.mybatisplus.MybatisConfiguration;
import com.baomidou.mybatisplus.entity.GlobalConfiguration;
import com.baomidou.mybatisplus.mapper.LogicSqlInjector;
import com.baomidou.mybatisplus.plugins.PaginationInterceptor;
import com.baomidou.mybatisplus.plugins.PerformanceInterceptor;
import com.baomidou.mybatisplus.spring.MybatisSqlSessionFactoryBean;
import com.warm.common.DBTypeEnum;
import com.warm.common.DynamicDataSource;
import org.apache.ibatis.plugin.Interceptor;
import org.apache.ibatis.session.SqlSessionFactory;
import org.apache.ibatis.type.JdbcType;
import org.mybatis.spring.annotation.MapperScan;
import org.springframework.beans.factory.annotation.Qualifier;
import org.springframework.boot.context.properties.ConfigurationProperties;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.context.annotation.Primary;
import javax.sql.DataSource;
import java.util.HashMap;
import java.util.Map;
/**
• @Author DGD
• @date 2018/2/6.
*/
@Configuration
@MapperScan({“com.warm.system.mapper*”})
public class MybatisPlusConfig {
/**
• mybatis-plus分页插件
• 文档:http://mp.baomidou.com
*/
@Bean
public PaginationInterceptor paginationInterceptor() {
PaginationInterceptor paginationInterceptor = new PaginationInterceptor();
//paginationInterceptor.setLocalPage(true);// 开启 PageHelper 的支持
return paginationInterceptor;
}
/**
• mybatis-plus SQL执行效率插件【生产环境可以关闭】
*/
@Bean
public PerformanceInterceptor performanceInterceptor() {
return new PerformanceInterceptor();
}
@Bean(name = “db1”)
@ConfigurationProperties(prefix = “spring.datasource.druid.db1” )
public DataSource db1 () {
return DruidDataSourceBuilder.create().build();
}
@Bean(name = “db2”)
@ConfigurationProperties(prefix = “spring.datasource.druid.db2” )
public DataSource db2 () {
return DruidDataSourceBuilder.create().build();
}
/**
• 动态数据源配置
• @return
*/
@Bean
@Primary
public DataSource multipleDataSource (@Qualifier(“db1”) DataSource db1,
@Qualifier(“db2”) DataSource db2 ) {
DynamicDataSource dynamicDataSource = new DynamicDataSource();
Map< Object, Object > targetDataSources = new HashMap<>();
targetDataSources.put(DBTypeEnum.db1.getValue(), db1 );
targetDataSources.put(DBTypeEnum.db2.getValue(), db2);
dynamicDataSource.setTargetDataSources(targetDataSources);
dynamicDataSource.setDefaultTargetDataSource(db1);
return dynamicDataSource;
}
@Bean(“sqlSessionFactory”)
public SqlSessionFactory sqlSessionFactory() throws Exception {
MybatisSqlSessionFactoryBean sqlSessionFactory = new MybatisSqlSessionFactoryBean();
sqlSessionFactory.setDataSource(multipleDataSource(db1(),db2()));
//sqlSessionFactory.setMapperLocations(new PathMatchingResourcePatternResolver().getResources(“classpath:/mapper/*/*Mapper.xml”));
MybatisConfiguration configuration = new MybatisConfiguration();
//configuration.setDefaultScriptingLanguage(MybatisXMLLanguageDriver.class);
configuration.setJdbcTypeForNull(JdbcType.NULL);
configuration.setMapUnderscoreToCamelCase(true);
configuration.setCacheEnabled(false);
sqlSessionFactory.setConfiguration(configuration);
sqlSessionFactory.setPlugins(new Interceptor[]{ //PerformanceInterceptor(),OptimisticLockerInterceptor()
paginationInterceptor()
});
sqlSessionFactory.setGlobalConfig(globalConfiguration());
return sqlSessionFactory.getObject();
}
@Bean
public GlobalConfiguration globalConfiguration() {
GlobalConfiguration conf = new GlobalConfiguration(new LogicSqlInjector());
conf.setLogicDeleteValue(“-1”);
conf.setLogicNotDeleteValue(“1”);
conf.setIdType(0);
conf.setMetaObjectHandler(new MyMetaObjectHandler());
conf.setDbColumnUnderline(true);
conf.setRefresh(true);
return conf;
}
}
MyMetaObjectHandler
package com.warm.config.mybatis;
import com.baomidou.mybatisplus.mapper.MetaObjectHandler;
import org.apache.ibatis.reflection.MetaObject;
import java.sql.Timestamp;
/**
• @Author DGD
• @date 2018/2/6.
*/
public class MyMetaObjectHandler extends MetaObjectHandler {
/**
• 字段为空自动填充,如果要使填充生效,一定在在实体类对应的字段上设置fill = FieldFill.INSERT字段!
*/
public void insertFill(MetaObject metaObject) {
// 更多查看源码测试用例
System.out.println(“*************************”);
System.out.println(“insert fill”);
System.out.println(“*************************”);
Object createTime = getFieldValByName(“createTime”, metaObject);//mybatis-plus版本2.0.9+
Timestamp timestamp = new Timestamp(System.currentTimeMillis());
if (createTime == null) {
setFieldValByName(“createTime”, timestamp, metaObject);//mybatis-plus版本2.0.9+
}
}
@Override
public void updateFill(MetaObject metaObject) {
//更新填充
System.out.println(“*************************”);
System.out.println(“update fill”);
System.out.println(“*************************”);
//mybatis-plus版本2.0.9+
setFieldValByName(“modifyTime”, new Timestamp(System.currentTimeMillis()), metaObject);
}
}
UserServiceImpl
package com.warm.system.service.impl;
import com.baomidou.mybatisplus.service.impl.ServiceImpl;
import com.warm.common.DBTypeEnum;
import com.warm.common.DataSourceSwitch;
import com.warm.system.entity.User;
import com.warm.system.mapper.OrderMapper;
import com.warm.system.mapper.UserMapper;
import com.warm.system.service.db1.UserService;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import java.math.BigDecimal;
import java.util.List;
/**
•
• 服务实现类
•
•
• @author dgd123
• @since 2018-02-10
*/
@Service
public class UserServiceImpl extends ServiceImpl<UserMapper, User> implements UserService {
@Autowired
private OrderMapper orderMapper;
@Override
public List getUserList() {
return selectList(null);
}
@DataSourceSwitch(DBTypeEnum.db2)
@Override
public BigDecimal getOrderPriceByUserId(Integer userId) {
return orderMapper.getPriceByUserId(userId);
}
}
application-dev.yml
server:
port: 8080
spring:
aop:
proxy-target-class: true
auto: true
datasource:
druid:
数据库 1
db1:
url: jdbc:mysql://120.78.5.210:3306/rosamdb?useUnicode=true&characterEncoding=utf8&autoReconnect=true&zeroDateTimeBehavior=convertToNull&transformedBitIsBoolean=true
username: root
password: root
driver-class-name: com.mysql.jdbc.Driver
initialSize: 5
minIdle: 5
maxActive: 20