springboot2.1.2 + hibernate5.2.11配置多数据源
来源:锐游网
项目需要用springboot2.1.2+hibernate5.2.11,配置多数据源时候因为dao层用的是公司封装的框架,没有实体没有映射,折腾了几天总算好了,记录一下
配置文件:application-dev.yml
spring:
datasource:
driverClassName: com.microsoft.sqlserver.jdbc.SQLServerDriver
type: com.alibaba.druid.pool.DruidDataSource
initialSize: 1
minIdle: 3
maxActive: 20
maxWait: 60000
timeBetweenEvictionRunsMillis: 60000
minEvictableIdleTimeMillis: 30000
testWhileIdle: true
testOnBorrow: false
testOnReturn: false
poolPreparedStatements: true
maxPoolPreparedStatementPerConnectionSize: 20
validationQuery: SELECT 1 FROM DUAL
# 配置监控统计拦截的filters,去掉后监控界面sql无法统计,'wall'用于防火墙
filters: stat,slf4j
# 通过connectProperties属性来打开mergeSql功能;慢SQL记录
connectionProperties: druid.stat.mergeSql=true;druid.stat.slowSqlMillis=5000
# 合并多个DruidDataSource的监控数据
#useGlobalDataSourceStat: true
source1:
url: jdbc:sqlserver://xxxx;instanceName=MSSQLSERVER;DatabaseName=xxxx;integratedSecurity=false
username: xxxx
password: xxxxxxx
source2:
url: jdbc:sqlserver://xxxx;DatabaseName=xxxx;integratedSecurity=false
username: xxxx
password: xxxxxxx
DataSourceAspect.java
@Aspect
@Order(1)
@Component
public class DataSourceAspect {
private Logger logger = LoggerFactory.getLogger(this.getClass());
// 切入点:service类的方法上(这个包的子包及所有包的里面的以Service结尾的类的任意方法名任意参数的方法,都讲被切到)
@Pointcut("execution(* com.xxxx.xxxxxx..*Service..*(..))")
public void dataSourcePointCut(){
System.out.println("dataSourcePointCut service");
}
@Before("dataSourcePointCut()")
private void before(JoinPoint joinPoint){
Object target = joinPoint.getTarget();
String method = joinPoint.getSignature().getName();
Class<?> classz = target.getClass();
Class<?>[] parameterTypes = ((MethodSignature) joinPoint.getSignature()).getMethod().getParameterTypes();
try {
Method m = classz.getMethod(method,parameterTypes);
// 如果 m 上存在切换数据源的注解,则根据注解内容进行数据源切换
if (m != null && m.isAnnotationPresent(TargetDataSource.class)){
TargetDataSource data = m.getAnnotation(TargetDataSource.class);
JdbcContextHolder.putDataSource(data.value().getName());
logger.info("》》》》》》》 current thread " + Thread.currentThread().getName() + " add 【 " + data.value().getName() + " 】 to ThreadLocal");
} else { // 如果不存在,则使用默认数据源
logger.info("》》》》》》》 use default datasource");
}
}catch (Exception e){
e.printStackTrace();
}
}
// 执行完切面后,将线程共享中的数据源名称清空
@After("dataSourcePointCut()")
public void after(JoinPoint joinPoint){
JdbcContextHolder.removeDataSource();
}
}
DataSourceConfig.java
@Configuration
public class DataSourceConfig {
private Logger logger = LoggerFactory.getLogger(this.getClass());
@Value("${spring.datasource.source1.url}")
private String dbUrl;
@Value("${spring.datasource.source1.username}")
private String username;
@Value("${spring.datasource.source1.password}")
private String password;
@Value("${spring.datasource.driverClassName}")
private String driverClassName;
@Value("${spring.datasource.validationQuery}")
private String validationQuery;
@Bean(name="source1")
public DataSource dataSourceMysql(){
System.out.println("----------------主配" + dbUrl);
DruidDataSource datasource = new DruidDataSource();
datasource.setUrl(dbUrl);
datasource.setUsername(username);
datasource.setPassword(password);
datasource.setDriverClassName(driverClassName);
datasource.setValidationQuery(validationQuery);
setDruidOptions(datasource); // 设置druid数据源的属性
return datasource;
}
@Value("${spring.datasource.source2.url}")
private String oracleUrl;
@Value("${spring.datasource.source2.username}")
private String oracleUsername;
@Value("${spring.datasource.source2.password}")
private String oraclePassword;
@Value("${spring.datasource.driverClassName}")
private String oracleDriverClassName;
@Value("${spring.datasource.driverClassName}")
private String oracleValidationQuery;
@Bean(name="source2")
public DataSource dataSourceOracle(){
System.out.println("----------------次配" + oracleUrl);
DruidDataSource datasource = new DruidDataSource();
datasource.setUrl(oracleUrl);
datasource.setUsername(oracleUsername);
datasource.setPassword(oraclePassword);
datasource.setDriverClassName(oracleDriverClassName);
datasource.setValidationQuery(oracleValidationQuery);
setDruidOptions(datasource); // 设置druid数据源的属性
return datasource;
}
// -----------------------------------------druid config-------------------------------------
@Value("${spring.datasource.initialSize}")
private int initialSize;
@Value("${spring.datasource.minIdle}")
private int minIdle;
@Value("${spring.datasource.maxActive}")
private int maxActive;
@Value("${spring.datasource.maxWait}")
private int maxWait;
@Value("${spring.datasource.timeBetweenEvictionRunsMillis}")
private int timeBetweenEvictionRunsMillis;
@Value("${spring.datasource.minEvictableIdleTimeMillis}")
private int minEvictableIdleTimeMillis;
@Value("${spring.datasource.testWhileIdle}")
private boolean testWhileIdle;
@Value("${spring.datasource.testOnBorrow}")
private boolean testOnBorrow;
@Value("${spring.datasource.testOnReturn}")
private boolean testOnReturn;
@Value("${spring.datasource.poolPreparedStatements}")
private boolean poolPreparedStatements;
@Value("${spring.datasource.maxPoolPreparedStatementPerConnectionSize}")
private int maxPoolPreparedStatementPerConnectionSize;
@Value("${spring.datasource.filters}")
private String filters;
@Value("{spring.datasource.connectionProperties}")
private String connectionProperties;
private void setDruidOptions(DruidDataSource datasource){
datasource.setInitialSize(initialSize);
datasource.setMinIdle(minIdle);
datasource.setMaxActive(maxActive);
datasource.setMaxWait(maxWait);
datasource.setTimeBetweenEvictionRunsMillis(timeBetweenEvictionRunsMillis);
datasource.setMinEvictableIdleTimeMillis(minEvictableIdleTimeMillis);
datasource.setTestWhileIdle(testWhileIdle);
datasource.setTestOnBorrow(testOnBorrow);
datasource.setTestOnReturn(testOnReturn);
datasource.setPoolPreparedStatements(poolPreparedStatements);
datasource.setMaxPoolPreparedStatementPerConnectionSize(maxPoolPreparedStatementPerConnectionSize);
try {
datasource.setFilters(filters);
} catch (SQLException e) {
logger.error("druid configuration initialization filter Exception", e);
}
datasource.setConnectionProperties(connectionProperties);
}
@Bean(name = "dynamicDataSource")
@Primary // 优先使用,多数据源
public DataSource dataSource(){
DynamicDataSource dynamicDataSource = new DynamicDataSource();
DataSource mysql = dataSourceMysql();
DataSource oracle = dataSourceOracle();
//设置默认数据源
dynamicDataSource.setDefaultTargetDataSource(mysql);
//配置多个数据源
Map<Object,Object> map = new HashMap<>();
map.put(DataSourceType.BJSH.getName(),mysql);
map.put(DataSourceType.KETTLE.getName(),oracle);
dynamicDataSource.setTargetDataSources(map);
return dynamicDataSource;
}
// 事务管理
@Bean
public PlatformTransactionManager txManager() {
// return new DataSourceTransactionManager(dataSource());
//注意如果maven引的包是spring-boot-starter-jdbc,则new DataSourceTransactionManager,如果引得是spring-boot-starter-data-jpa ,则new下面这个,这个坑蹲了好久才发现,不然事务不起作用
JpaTransactionManager jpaTransactionManager = new JpaTransactionManager();
jpaTransactionManager.setDataSource(dataSource());
return jpaTransactionManager;
}
@Bean(name="druidServlet")
public ServletRegistrationBean druidServlet() {
ServletRegistrationBean reg = new ServletRegistrationBean();
reg.setServlet(new StatViewServlet());
reg.addUrlMappings("/druid/*");
reg.addInitParameter("allow", ""); // 白名单
return reg;
}
@Bean(name = "filterRegistrationBean")
public FilterRegistrationBean filterRegistrationBean() {
FilterRegistrationBean filterRegistrationBean = new FilterRegistrationBean();
filterRegistrationBean.setFilter(new WebStatFilter());
filterRegistrationBean.addUrlPatterns("/*");
filterRegistrationBean.addInitParameter("exclusions", "*.js,*.gif,*.jpg,*.png,*.css,*.ico,/druid/*");
filterRegistrationBean.addInitParameter("profileEnable", "true");
filterRegistrationBean.addInitParameter("principalCookieName","USER_COOKIE");
filterRegistrationBean.addInitParameter("principalSessionName","USER_SESSION");
filterRegistrationBean.addInitParameter("DruidWebStatFilter","/*");
return filterRegistrationBean;
}
}
DataSourceType.java
public enum DataSourceType {
SOURCE1("source1"),
SOURCE2("source2");
private String name;
DataSourceType(String name) {
this.name = name;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
}
DynamicDataSource.java
public class DynamicDataSource extends AbstractRoutingDataSource {
/** 数据源路由,此方法用于产生要选取的数据源逻辑名称 */
@Override
protected Object determineCurrentLookupKey() {
//从共享线程中获取数据源名称
return JdbcContextHolder.getDataSource();
}
}
JdbcContextHolder.java
public class JdbcContextHolder {
/** 本地线程共享对象(保证在同一线程下切换后不要被其他线程修改) */
private final static ThreadLocal<String> local = new ThreadLocal<>();
public static void putDataSource(String name){
local.set(name);
}
public static String getDataSource(){
return local.get();
}
public static void removeDataSource(){
local.remove();
}
}
TargetDataSource.java
@Documented
@Retention(RetentionPolicy.RUNTIME)
@Target(ElementType.METHOD)
public @interface TargetDataSource {
DataSourceType value() default DataSourceType.BJSH;
}
DataServiceApplication.java
@EnableTransactionManagement
//配上开启事务管理
@EnableAspectJAutoProxy(exposeProxy = true)
@SpringBootApplication(exclude={DataSourceAutoConfiguration.class})
//这里需要排除掉自动装载的datasource
@ComponentScan(value = {"com.xxxxxxx.xxxxxxx.*", "com.xxxxxx.*", "com.xxxxx.xxxxx.*"},excludeFilters = @ComponentScan.Filter(type = FilterType.CUSTOM, classes = DruidCinfugExcludeFilter.class))
//引入公司的包,因为公司的包里封装了DruidConfig,所以需要排除掉
public class DataServiceApplication extends SpringBootServletInitializer {
public static void main(String[] args) {
SpringApplication.run(DataServiceApplication.class, args);
}
@Override
protected SpringApplicationBuilder configure(SpringApplicationBuilder application) {
return application.sources(DataServiceApplication.class);
}
}
参考:
另外一个参考的找不到了
因篇幅问题不能全部显示,请点此查看更多更全内容