application.yml的配置连接两个数据源
一个master,一个slave1:
spring:
datasource:
master:
type: com.alibaba.druid.pool.DruidDataSource
url: jdbc:postgresql://10.111.111.111:5432/aaa
username: reta
password: reta
driver-class-name: org.postgresql.Driver
name: master
filters: stat
slave1:
type: com.alibaba.druid.pool.DruidDataSource
username: reta
password: reta
driver-class-name: oracle.jdbc.OracleDriver
url: jdbc:oracle:thin:@//10.111.11.112:1535/aaa
name: slave1
filters: stat
spring.jpa.properties.hibernate.temp.use_jdbc_metadata_defaults: false
spring.jpa.database-platform: org.hibernate.dialect.PostgreSQL9Dialect
注意,上面配置的最后两行,是因为要连接postgreSQL数据库才需要的。
新建一个包,存放相关配置文件。
接下来,将对图片中的文档进行说明。
DataSource
import java.lang.annotation.ElementType;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import java.lang.annotation.Target;
@Retention(RetentionPolicy.RUNTIME)
@Target({
ElementType.METHOD
})
public @interface DataSource {
String value() default "master";
}
在这里设置默认连接的数据库master。
DataSourceContextHolder
public class DataSourceContextHolder {
public static final String Master = "master";
public static final String Slave1 = "slave1";
private static final ThreadLocal<String> contextHolder = new ThreadLocal<>();
public static void setDataSource(String name){
contextHolder.set(name);
}
public static String getDataSource(){
return contextHolder.get();
}
public static void cleanDataSource(){
contextHolder.remove();
}
}
DynamicDataSource
import org.springframework.jdbc.datasource.lookup.AbstractRoutingDataSource;
public class DynamicDataSource extends AbstractRoutingDataSource {
@Override
protected Object determineCurrentLookupKey() {
return DataSourceContextHolder.getDataSource();
}
}
DynamicDataSourceAspect
import org.aspectj.lang.annotation.After;
import org.aspectj.lang.annotation.Aspect;
import org.aspectj.lang.annotation.Before;
import org.aspectj.lang.annotation.Pointcut;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.core.annotation.Order;
import org.springframework.stereotype.Component;
@Aspect
@Component
@Order(1) //需要加入切面排序
public class DynamicDataSourceAspect {
private Logger logger = LoggerFactory.getLogger(DynamicDataSourceAspect.class);
//切入点只对@Service注解的类上的@DataSource方法生效
@Pointcut(value="@within(org.springframework.stereotype.Service) && @annotation(dataSource)" )
public void dynamicDataSourcePointCut(DataSource dataSource){}
@Before(value = "dynamicDataSourcePointCut(dataSource)")
public void switchDataSource(DataSource dataSource) throws Throwable{
logger.info("##############数据源 :{}###############",dataSource.value());
DataSourceContextHolder.setDataSource(dataSource.value());
}
@After(value="dynamicDataSourcePointCut(dataSource)")
public void after(DataSource dataSource){
DataSourceContextHolder.cleanDataSource();
}
}
MultipleDateSourceConfig
import com.alibaba.druid.pool.DruidDataSource;
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;
@Configuration
public class MultipleDateSourceConfig {
@Bean("master")
@ConfigurationProperties(prefix = "spring.datasource.master")
public DataSource creeateMasterDataSource(){
return new DruidDataSource();
}
@Bean("slave1")
@ConfigurationProperties(prefix = "spring.datasource.slave1")
public DataSource creeateSlave1DataSource(){
return new DruidDataSource();
}
/**
* 设置动态数据源,通过@Primary 来确定主DataSource
* @return
*/
@Bean
@Primary
public DataSource createDynamicdataSource(@Qualifier("master") DataSource master, @Qualifier("slave1") DataSource slave1){
DynamicDataSource dynamicDataSource = new DynamicDataSource();
//设置默认数据源
dynamicDataSource.setDefaultTargetDataSource(master);
//配置多数据源
Map<Object, Object> map = new HashMap<>();
map.put("master",master);
map.put("slave1",slave1);
dynamicDataSource.setTargetDataSources(map);
return dynamicDataSource;
}
}
在调用的时候,只需在service实现类中,注明数据库就好
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import java.util.List;
@Service
public class InsertServiceImpl implements InsetService {
@Autowired
private InsertMapper insertMapper;
@DataSource(DataSourceContextHolder.Slave1)
@Transactional
@Override
public boolean insertDataForLastWeek(List<DataSyn> list) {
return insertMapper.insertDataForLastWeek(list);
}
@DataSource(DataSourceContextHolder.Slave1)
@Transactional
@Override
public int selectTotalNumber() {
return insertMapper.selectTotalNumber();
}
}
如此,便成功实现动态连接数据库。