当前位置: 首页 > news >正文

淘宝联盟怎么样做网站威海做企业网站

淘宝联盟怎么样做网站,威海做企业网站,门户网站建设工具,谷歌三件套一键安装使用AbstractRoutingDataSource实现多数据源 与 获取mapper上注解 背景 随着业务发展速度越来越快#xff0c;数据的增长也呈现倍数级别增长#xff0c;数据库的压力#xff0c;对于查询和写入等所有操作#xff0c;都依赖于主库#xff0c;其实有一些对于时效性要求不高…使用AbstractRoutingDataSource实现多数据源 与 获取mapper上注解 背景 随着业务发展速度越来越快数据的增长也呈现倍数级别增长数据库的压力对于查询和写入等所有操作都依赖于主库其实有一些对于时效性要求不高的场景无需使用主库查询可以使用从库来分摊主库的压力提升数据库集群整体的吞吐量 处理思路 其实处理思路共有两种 1. 我们创建两个数据源不同的数据源扫描不同的包.         也就是查询从库或者查询主库是通过不同的mapper文件物理隔离的优势就是开发简单快速搭建不用担心侵入原有逻辑。缺点也是显而易见的如果一个sql在某些场景下需要主库查询另外场景需要从库查询那么我们要写两套sql如果有新增字段等ddl操作时我们要改两遍sql由于比较简单本文不做描述。 2. 使用动态数据源配置         在多个数据源之上抽象出来一个虚拟的动态数据源等到执行sql的前一步我们才会选择哪个数据源执行优点是能够更精细化的管控sql执行缺点的话就是开发稍微复杂些 动态数据源的执行逻辑 我们需要先了解下spring的AbstractRoutingDataSource spring提供了一套数据库路由方案我们重写determineCurrentLookupKey 方法将想要的数据库返回即可。 以spring boot 为例 一、 mysql的基本配置 首先配置主库和从库的数据源这个是前提 Bean(name mysqlDataSource) Primary public DataSource mysqlDataSource() {DruidDataSource dataSource new DruidDataSource();dataSource.setDriverClassName(driverClass);dataSource.setUrl(url);dataSource.setUsername(user);dataSource.setPassword(password);dataSource.setMaxActive(300);dataSource.setKeepAlive(true);dataSource.setMaxWait(60000);dataSource.setValidationQuery(SELECT x);dataSource.setMinEvictableIdleTimeMillis(300000);dataSource.setTestWhileIdle(true);dataSource.setTestOnBorrow(true);dataSource.setTestOnReturn(false);return dataSource; } /*** 从库主库数据源*/ Bean(name mysqlSlaveDataSource) public DataSource mysqlSlaveDataSource() {DruidDataSource dataSource new DruidDataSource();dataSource.setDriverClassName(driverClass);dataSource.setUrl(url);dataSource.setUsername(readUser);dataSource.setPassword(passwordRead);dataSource.setMaxActive(300);dataSource.setKeepAlive(true);dataSource.setMaxWait(60000);dataSource.setValidationQuery(SELECT x);dataSource.setMinEvictableIdleTimeMillis(300000);dataSource.setTestWhileIdle(true);dataSource.setTestOnBorrow(true);dataSource.setTestOnReturn(false);return dataSource; }配置动态数据源将多数据源注入进动态数据源并设置默认的数据源 Bean(name dynamicDataSource) public DynamicDataSource dynamicDataSource(Qualifier(mysqlDataSource) DataSource mysqlDataSource,Qualifier(mysqlSlaveDataSource) DataSource mysqlSlaveDataSource) {MapObject, Object targetDataSources Maps.newHashMap();targetDataSources.put(DataSourceEnum.MASTER, mysqlDataSource);targetDataSources.put(DataSourceEnum.SLAVE, mysqlSlaveDataSource);return new DynamicDataSource(mysqlDataSource, targetDataSources); }将动态数据源设置到sql的sessionFactory Bean(name mysqlSqlSessionFactory) Primary public SqlSessionFactory masterSqlSessionFactory(Qualifier(dynamicDataSource) DataSource dynamicDataSource) throws Exception {final SqlSessionFactoryBean sessionFactory new SqlSessionFactoryBean();sessionFactory.setDataSource(dynamicDataSource);sessionFactory.setMapperLocations(new PathMatchingResourcePatternResolver().getResources(MysqlDataSourceConfig.MAPPER_LOCATION));// 配置org.apache.ibatis.session.Configuration configuration new org.apache.ibatis.session.Configuration();configuration.setMapUnderscoreToCamelCase(true);configuration.setDefaultStatementTimeout(30);configuration.addInterceptor(new MybatisUMPInterceptor());sessionFactory.setConfiguration(configuration);return sessionFactory.getObject(); }二、 新增的配置 新增加库的枚举定义 package com.common.enums;/*** 数据源配置枚举** author wangzym*/ public enum DataSourceEnum {/*** 使用主库*/MASTER(1, 主库),/*** 使用从库*/SLAVE(2, 从库);/*** /*** 编码*/private Integer code;/*** 描述*/private String desc;DataSourceEnum(Integer code, String desc) {this.code code;this.desc desc;}public Integer getCode() {return this.code;}public String getDesc() {return this.desc;}public static DataSourceEnum getByCode(Integer code) {if (code null) {return null;}for (DataSourceEnum dataSourceEnum : DataSourceEnum.values()) {if (dataSourceEnum.getCode().equals(code)) {return dataSourceEnum;}}return null;} }动态数据源的定义需要继承spring的AbstractRoutingDataSource package com.test.datasource;import com.alibaba.fastjson.JSON; import com.test.SettleCheckException; import lombok.extern.slf4j.Slf4j; import org.springframework.jdbc.datasource.lookup.AbstractRoutingDataSource;import javax.sql.DataSource; import java.util.Map;/*** 动态切换数据源类** author wangzym*/ Slf4j public class DynamicDataSource extends AbstractRoutingDataSource {public DynamicDataSource(DataSource defaultTargetDataSource, MapObject, Object targetDataSources) {//不符合配置条件直接中断启动流程if (defaultTargetDataSource null || targetDataSources null || targetDataSources.isEmpty()) {throw new SettleCheckException(默认数据源和可切换的数据源不允许为空!请检查 spring-config-datasource-druid.xml - dynamicDataSource 对应配置);}//设置默认数据源super.setDefaultTargetDataSource(defaultTargetDataSource);//设置用于切换的数据源super.setTargetDataSources(targetDataSources);//初始化本地的数据源记录super.afterPropertiesSet();}Overrideprotected Object determineCurrentLookupKey() {log.debug(当前线程使用SQL的数据库是:{}, JSON.toJSONString(DynamicDataSourceHolder.getDataSource()));return DynamicDataSourceHolder.getDataSource();}}新增注解 package com.test.datasource;import com.test.DataSourceEnum;import java.lang.annotation.*;/*** 切换数据源注解默认连接主库* 要在mapper上加此注解才可以* p*/ Inherited Retention(RetentionPolicy.RUNTIME) Target(ElementType.METHOD) Documented public interface SwitchDataSource {DataSourceEnum name() default DataSourceEnum.MASTER; }拦截器改造需要拦截sql此方法可以直接拦截sql执行此方法要重点理解是mybatis的拦截方案其中Intercepts可以通过不同的类型来进行不同的拦截此处拦截所有执行的sql直接获取mapper上的注解会获取不到需要通过反射的方式来获取需要重点注意此处不是本文的重点有兴趣可以了解mybatis源码。 package com.test.interceptor;import com.test.DuccConstants; import com.test.enums.DataSourceEnum; import com.test.datasource.DynamicDataSourceHolder;Intercepts({Signature(type Executor.class, method query, args {MappedStatement.class, Object.class, RowBounds.class, ResultHandler.class}),Signature(type Executor.class, method query, args {MappedStatement.class, Object.class, RowBounds.class, ResultHandler.class, CacheKey.class, BoundSql.class}),Signature(type Executor.class, method update, args {MappedStatement.class, Object.class}),}) Slf4j public class MybatisUMPInterceptor implements Interceptor {Value(${test.current.env:pre})private static String env;static {env System.getProperty(current.env, pre);log.info(当前切面的环境为:{}, env);}Overridepublic Object intercept(Invocation invocation) throws Throwable {CallerInfo callerInfo null;try {//1.处理数据源切换SwitchDataSource chooseDataSource getSwitchDbAnnotation((MappedStatement) invocation.getArgs()[0]);if (null ! chooseDataSource DuccConstants.allowedMultiDb()) {//默认会使用MASTER数据源 如果开启事务了,而且当前数据源不是MASTER会强制切换为MASTERDynamicDataSourceHolder.setDataSource(chooseDataSource.name());if (TransactionSynchronizationManager.isActualTransactionActive() DataSourceEnum.SLAVE.equals(chooseDataSource.name())) {DynamicDataSourceHolder.setDataSource(DataSourceEnum.MASTER);}} else {DynamicDataSourceHolder.setDataSource(DataSourceEnum.MASTER);}//2.埋点监控Object[] args invocation.getArgs();MappedStatement ms (MappedStatement) args[0];//ump key可以自定义String jKey String.format(%s_MyBatis.%s, env, ms.getId());if (DynamicDataSourceHolder.getDataSource() ! null DynamicDataSourceHolder.getDataSource().equals(DataSourceEnum.SLAVE)) {jKey jKey _slave;}callerInfo Profiler.registerInfo(jKey, false, true);} catch (Exception ignore) {//ignorelog.warn(切面执行出现异常:{}, ignore.getStackTrace(), ignore);}try {return invocation.proceed();} catch (Throwable e) {try {if (null ! callerInfo) {Profiler.functionError(callerInfo);}} catch (Exception ignore) {//ignore}throw e;} finally {try {if (null ! callerInfo) {Profiler.registerInfoEnd(callerInfo);}} catch (Exception ignore) {//ignore}}}private SwitchDataSource getSwitchDbAnnotation(MappedStatement mappedStatement) {SwitchDataSource annotation null;try {String id mappedStatement.getId();String className id.substring(0, id.lastIndexOf(.));String methodName id.substring(id.lastIndexOf(.) 1);final Method[] method Class.forName(className).getMethods();for (Method me : method) {if (me.getName().equals(methodName) me.isAnnotationPresent(SwitchDataSource.class)) {return me.getAnnotation(SwitchDataSource.class);}}} catch (Exception ex) {log.error(, ex);}return annotation;}Overridepublic Object plugin(Object target) {return Plugin.wrap(target, this);}Overridepublic void setProperties(Properties properties) {} }在mapper上打注解标记 SwitchDataSource(name DataSourceEnum.SLAVE) Long queryTaskOfShopCount(GeneralFeeDetailDTO generalFeeDetailDTO);至此mysql 动态路由到指定数据库就讲解完成。
http://www.hkea.cn/news/14524144/

相关文章:

  • 东莞网页设计哪家设计网站好?wordpress获取当前文章名称
  • 网站运营这么做电脑平面设计主要做什么
  • 东莞网站空间网站虚拟空间过期
  • 微信企业网站 源码下载做影片的网站描述
  • 建站之家官网wordpress最近更新模块
  • 网站关键词查询网站建设jz518
  • 做网站有钱在线网站建设平台哪个好
  • 制造企业网站的建设目标深圳平台推广
  • 建视频网站系统吗商城版免费网站制作
  • 网站有权重可以对title做更改国内十大软件外包公司
  • 湛江网站建设方案托管网站建设公司网页
  • 上海网站建设求职简历广西建设网官方网桂建云
  • seo可以提升企业网站的h5编辑器有哪些软件
  • 网站建设的需求方案建行官网
  • python怎么做抢课网站连云港网站建设案例
  • 机加工外贸网站c网站制作
  • diy网站开发公司湖南邵阳调整多个风险区
  • 网站开发服务费算无形资产吗企业工商注册查询
  • 福建省建设厅网站人员沂南建设局网站
  • 什么网站收录快城厢区住房和城乡建设局网站
  • 网站宣传的方法网站搭建与服务器配置
  • 灯塔网站建设黑马程序员视频库
  • pc开奖网站建设手游源码网
  • ktv在那些网站做宣传效果好上海网站编辑招聘
  • 做肯德基玻璃门网站供灯放生网站开发
  • 网站建设与维护流程图网络系统设计与管理
  • 微信网站开发教程视频教程wordpress+andriod
  • 宜昌住房和城乡建设厅网站广西桂平建设局网站
  • 好的网站建设技术好项目寻找个人投资
  • 职业学院网站建设高端房产网站建设