Spring Boot集成Mybatis双数据源
来源:互联网 发布:算法基础 pdf 下载 编辑:程序博客网 时间:2024/06/05 02:07
这里用到了Spring Boot + Mybatis + DynamicDataSource配置动态双数据源,可以动态切换数据源实现数据库的读写分离。
添加依赖
加入Mybatis启动器,这里添加了Druid连接池、Oracle数据库驱动为例。
<dependency> <groupId>org.mybatis.spring.boot</groupId> <artifactId>mybatis-spring-boot-starter</artifactId></dependency><dependency> <groupId>com.alibaba</groupId> <artifactId>druid</artifactId></dependency><dependency> <groupId>com.oracle</groupId> <artifactId>ojdbc6</artifactId></dependency>
添加启动类
@EnableMybatis@EnableTransactionManagement@SpringBootApplication(exclude = { DataSourceAutoConfiguration.class })public class Application { public static void main(String[] args) { SpringApplication.run(ServiceApplication.class, args); }}
@SpringBootApplication(exclude = { DataSourceAutoConfiguration.class }):
这里用到了双数据源,需要排除数据源的自动配置,如果只有一个数据源用Spring Boot的自动配置就行。
@EnableTransactionManagement:开启事务支持。
@EnableMybatis:开启Mybatis功能
@Target(ElementType.TYPE)@Retention(RetentionPolicy.RUNTIME)@Documented@Import(MybatisConfig.class)public @interface EnableMybatis {}
Mybatis配置类
@Configuration@MapperScan(basePackages = DSConfig.BASE_PACKAGES)public class MybatisConfig implements DSConfig { @Primary @Bean public DynamicDataSource dynamicDataSource(@Qualifier(DB_MASTER) DataSource master, @Qualifier(DB_SLAVE) DataSource slave) { Map<Object, Object> dsMap = new HashMap<>(); dsMap.put(DB_MASTER, master); dsMap.put(DB_MASTER, slave); DynamicDataSource dynamicDataSource = new DynamicDataSource(); dynamicDataSource.setDefaultTargetDataSource(master); dynamicDataSource.setTargetDataSources(dsMap); return dynamicDataSource; } @Bean public PlatformTransactionManager transactionManager(DynamicDataSource dynamicDataSource) { return new DataSourceTransactionManager(dynamicDataSource); } @Bean public SqlSessionFactory sqlSessionFactory(DynamicDataSource dynamicDataSource) throws Exception { SqlSessionFactoryBean sessionFactory = new SqlSessionFactoryBean(); sessionFactory.setDataSource(dynamicDataSource); sessionFactory.setMapperLocations( ((ResourcePatternResolver) new PathMatchingResourcePatternResolver()) .getResources(DSConfig.MAPPER_LOCATIONS)); return sessionFactory.getObject(); }}
DSConfig常量类:
public interface DSConfig { String DS_PREFIX = "spring.datasource"; String DS_ACTIVE = "active"; String DB_MASTER = "db-master"; String DB_SLAVE = "db-slave"; String DRUID = "druid"; String DRUID_MONITOR_USERNAME = "spring.druid.username"; String DRUID_MONITOR_PASSWORD = "spring.druid.password"; String DRUID_MONITOR_URL = "/druid/*"; String DRUID_FILTER_EXCLUSIONS = "*.js,*.gif,*.jpg,*.png,*.css,*.ico,/druid/*"; String DRUID_FILTER_URL = "/*"; String BASE_PACKAGES = "com.example.**.mapper"; String MAPPER_LOCATIONS = "mapper/**/*.xml";}
连接池配置类
Druid连接池的自动配置类:
@Configuration@Import({ PropertiesConfig.class })@ConditionalOnClass(DruidDataSource.class)@ConditionalOnProperty(prefix = DSConfig.DS_PREFIX, value = DSConfig.DS_ACTIVE, havingValue = DSConfig.DRUID)public class DruidAutoConfig implements DSConfig { private Logger logger = LoggerUtils.getLogger(this); @Bean(name = DB_MASTER, initMethod = "init", destroyMethod = "close") public DataSource dataSourceMaster(DruidMasterProperties masterProperties) throws SQLException { logger.debug("master properties: {}", masterProperties.toString()); DruidDataSource dds = new DruidDataSource(); dds.setDriverClassName(masterProperties.getDriverClassName()); dds.setUrl(masterProperties.getUrl()); dds.setUsername(masterProperties.getUsername()); dds.setPassword(masterProperties.getPassword()); dds.setInitialSize(masterProperties.getInitialSize()); dds.setMinIdle(masterProperties.getMinIdle()); dds.setMaxActive(masterProperties.getMaxActive()); dds.setMaxWait(masterProperties.getMaxWait()); dds.setTimeBetweenEvictionRunsMillis(masterProperties.getTimeBetweenEvictionRunsMillis()); dds.setMinEvictableIdleTimeMillis(masterProperties.getMinEvictableIdleTimeMillis()); dds.setValidationQuery(masterProperties.getValidationQuery()); dds.setTestOnBorrow(masterProperties.isTestOnBorrow()); dds.setTestWhileIdle(masterProperties.isTestWhileIdle()); dds.setTestOnReturn(masterProperties.isTestOnReturn()); dds.setPoolPreparedStatements(masterProperties.isPoolPreparedStatements()); dds.setMaxPoolPreparedStatementPerConnectionSize( masterProperties.getMaxPoolPreparedStatementPerConnectionSize()); dds.setFilters(masterProperties.getFilters()); return dds; } @Bean(name = DB_SLAVE, initMethod = "init", destroyMethod = "close") public DataSource dataSourceSlave(DruidSlaveProperties slaveProperties) throws SQLException { logger.debug("slave properties: {}", slaveProperties.toString()); DruidDataSource dds = new DruidDataSource(); dds.setDriverClassName(slaveProperties.getDriverClassName()); dds.setUrl(slaveProperties.getUrl()); dds.setUsername(slaveProperties.getUsername()); dds.setPassword(slaveProperties.getPassword()); dds.setInitialSize(slaveProperties.getInitialSize()); dds.setMinIdle(slaveProperties.getMinIdle()); dds.setMaxActive(slaveProperties.getMaxActive()); dds.setMaxWait(slaveProperties.getMaxWait()); dds.setTimeBetweenEvictionRunsMillis(slaveProperties.getTimeBetweenEvictionRunsMillis()); dds.setMinEvictableIdleTimeMillis(slaveProperties.getMinEvictableIdleTimeMillis()); dds.setValidationQuery(slaveProperties.getValidationQuery()); dds.setTestOnBorrow(slaveProperties.isTestOnBorrow()); dds.setTestWhileIdle(slaveProperties.isTestWhileIdle()); dds.setTestOnReturn(slaveProperties.isTestOnReturn()); dds.setPoolPreparedStatements(slaveProperties.isPoolPreparedStatements()); dds.setMaxPoolPreparedStatementPerConnectionSize( slaveProperties.getMaxPoolPreparedStatementPerConnectionSize()); dds.setFilters(slaveProperties.getFilters()); return dds; } @Bean public ServletRegistrationBean druidServletRegistrationBean(EnvConfig env) { String username = env.getStringValue(DSConfig.DRUID_MONITOR_USERNAME); String password = env.getStringValue(DSConfig.DRUID_MONITOR_PASSWORD); return new ServletRegistrationBean(new DruidStatViewServlet(username, password), DSConfig.DRUID_MONITOR_URL); } @Bean public FilterRegistrationBean druidFilterRegistrationBean() { WebStatFilter wsf = new WebStatFilter(); FilterRegistrationBean filterRegistrationBean = new FilterRegistrationBean(); filterRegistrationBean.setFilter(wsf); filterRegistrationBean.setUrlPatterns(Arrays.asList(DSConfig.DRUID_FILTER_URL)); filterRegistrationBean.setInitParameters( Collections.singletonMap("exclusions", DSConfig.DRUID_FILTER_EXCLUSIONS)); return filterRegistrationBean; }}
根据类路径下有DruidDataSource这个类即有Druid这个jar包和配置文件中spring.datasource.active=druid才开启对Druid连接池的自动配置。
导入的配置文件:
@Configuration@ComponentScan(basePackages = "com.example.common.config.properties")public class PropertiesConfig {}
DruidMasterProperties、DruidSlaveProperties属性文件读取的配置省略。
连接池监控配置类:
public class DruidStatViewServlet extends StatViewServlet { private static final long serialVersionUID = 1L; private String username; private String password; @Override public String getInitParameter(String name) { if ("loginUsername".equals(name)) { return username; } if ("loginPassword".equals(name)) { return password; } return super.getInitParameter(name); } public DruidStatViewServlet(String username, String password) { super(); this.username = username; this.password = password; } public String getUsername() { return username; } public String getPassword() { return password; }}
在META-INF/spring.factories中加入Druid自动配置映射:
org.springframework.boot.autoconfigure.EnableAutoConfiguration=\com.example.common.config.ds.DruidAutoConfig
切换数据源
切换数据源注解:
@Target(ElementType.METHOD)@Retention(RetentionPolicy.RUNTIME)@Documentedpublic @interface DS { String value() default DSConfig.DB_MASTER;}
动态数据源类:
public class DynamicDataSource extends AbstractRoutingDataSource { private final Logger logger = LoggerUtils.getLogger(this); @Override protected Object determineCurrentLookupKey() { logger.debug("当前数据源为{}", DataSourceContextHolder.getDS()); return DataSourceContextHolder.getDS(); }}
动态数据源AOP实现类:
@Aspect@Componentpublic class DynamicDataSourceAspect { @Before("@annotation(DS)") public void beforeSwitchDS(JoinPoint point) { Class<?> className = point.getTarget().getClass(); String methodName = point.getSignature().getName(); Class<?>[] argClass = ((MethodSignature) point.getSignature()).getParameterTypes(); String dataSource = DataSourceContextHolder.DEFAULT_DS; try { Method method = className.getMethod(methodName, argClass); if (method.isAnnotationPresent(DS.class)) { DS annotation = method.getAnnotation(DS.class); dataSource = annotation.value(); } } catch (Exception e) { e.printStackTrace(); } DataSourceContextHolder.setDS(dataSource); } @After("@annotation(DS)") public void afterSwitchDS(JoinPoint point) { DataSourceContextHolder.clearDS(); }}
绑定当前线程数据源类:
public class DataSourceContextHolder { public static final String DEFAULT_DS = DSConfig.DB_MASTER; private static final ThreadLocal<String> DS_HOLDER = new ThreadLocal<>(); public static void setDS(String dbType) { DS_HOLDER.set(dbType); } public static String getDS() { return (DS_HOLDER.get()); } public static void clearDS() { DS_HOLDER.remove(); }}
推荐阅读
分享一套高级视频教程:Dubbo+Zookeeper+ActiveMQ+Redis系列
分享一套分布式架构设计高级视频教程
分享一套Hadoop全套视频教程系列
去BAT面试完的Mysql面试题总结(55道,带完整答案)
阿里高级Java面试题(首发,70道,带详细答案)
2017派卧底去阿里、京东、美团、滴滴带回来的面试题及答案
Spring面试题(70道,史上最全)
通往大神之路,百度Java面试题前200页。
分享Java干货,高并发编程,热门技术教程,微服务及分布式技术,架构设计,区块链技术,人工智能,大数据,Java面试题,以及前沿热门资讯等。
- Spring Boot集成Mybatis双数据源
- mybatis+spring双数据源配置
- Spring + Spring MVC + mybatis 配置双数据源及用法
- Spring Boot 集成MyBatis
- Spring Boot 集成Mybatis
- spring-boot集成mybatis
- Spring boot集成Mybatis
- Spring Boot 集成MyBatis
- spring boot集成mybatis
- Spring Boot集成MyBatis
- Spring Boot 集成MyBatis
- Spring Boot 集成MyBatis
- Spring Boot 集成MyBatis
- Spring Boot 集成MyBatis
- Spring Boot集成mybatis
- Spring Boot集成Mybatis
- spring boot 集成mybatis
- Spring Boot 集成MyBatis
- 【资源更新】Hadoop全套教程
- 高级教程分享:Dubbo+Zookeeper+ActiveMQ+Redis等。
- 智能蛇
- jq进行table动态增删上下移动
- 5分钟带你理解一致性Hash算法。
- Spring Boot集成Mybatis双数据源
- Spring Boot配置加载顺序
- 剑指offer-36-数组中的逆序对
- Spring Boot配置随机数
- HashMap 源码解析
- 分布式服务防雪崩熔断器,Hystrix理论+实战。
- GitHub上11月份最热门的Java项目
- Mycat
- 服务高可用:幂等性设计