1.总体思路:
通过约定的XML规则(分表分库规则)和 封装jdbc的Connection和PreparedStatement来实现SQL解析,sql路由和sql重写。

2. 3个核心类:ConnectionWrapper(JDBC Connection包装),PreparedStatementWrapper( JDBC PreparedStatement包装),SimpleExecutor(sql执行器,类似mybatis的SimpleExecutor)

3. 3个上下文传参数:ConnectionContext,StatementContext,transactionContext。

4. 真正干活的类:

(1)DefaultStatementContextBuilder类:解析SQL并保存BatchItem到StatementContext,--作者貌似直接用的mycat里面的sql解析的代码,直接拿来主义实现价值啊。

public StatementContext build(String sql, StatementContext context)          throws SQLException {     if (context == null) {          context = new StatementContext();            StatementContext.setContext(context);         if (logger.isDebugEnabled()) {                logger.debug("create context!sql=" + sql);            }     }     if (context.getCurrentBatch().getSql() == null) {           context.getCurrentBatch().setSql(sql);        }

       StatementContextHandler handler = null;      if (context.isBatch()) {          handler = HandlerFactory.create(StatementType.BATCH);            StatementContext resultContext = handler.handle(sql, context);           processPreparedValues(resultContext);         return resultContext;     }

       TrackerExecutor.trackBegin(TrackPoint.PARSE_SQL, sql);        SQLParser parser = StatementHelper.createSQLParser();        try {         DMLStatementNode statementNode = (DMLStatementNode) parser                   .parseStatement(sql);         switch (statementNode.getNodeType()) {            case NodeTypes.CURSOR_NODE:               handler = HandlerFactory.create(StatementType.SELECT);               break;            case NodeTypes.DELETE_NODE:               handler = HandlerFactory.create(StatementType.DELETE);               break;            case NodeTypes.UPDATE_NODE:               handler = HandlerFactory.create(StatementType.UPDATE);               break;            case NodeTypes.INSERT_NODE:               handler = HandlerFactory.create(StatementType.INSERT);               break;            case NodeTypes.CALL_STATEMENT_NODE:               handler = HandlerFactory.create(StatementType.CALLABLE);             break;            }

           StatementContext resultContext = handler.handle(statementNode,                   context);

           TrackerExecutor.trackEnd(TrackPoint.PARSE_SQL);

         processPreparedValues(resultContext);         return resultContext;

       } catch (StandardException se) {          System.out.println("sql parse error, sql:"+sql);           se.printStackTrace();     } catch (Exception e) {           e.printStackTrace();      }     processPreparedValues(context);       return context;   }

(2)DefaultTargetDispatcher:根据batchItem和batchItem中的tableInfo获取路由信息和重写SQL,达到路由到指定的分库分表的目的

Set<RouteTarget> getSpecifyTargets(TableInfo tableInfo, BatchItem batchItem) {     Set<RouteTarget> targetSet = new LinkedHashSet<RouteTarget>();       Configurations configurations = Configurations.getInstance();

      /**        * 解析where中符合分库分表字段的值      */       Map<String, List<TableColumn>> resolveColumns = RouteHelper              .getResolveColumns(tableInfo.getOrgName(),                        batchItem.getAnalyzeResult());        List<Map<String, Object>> parameters = RouteHelper               .getParameterValues(resolveColumns);      Set<Integer> indexs = new HashSet<Integer>();        TableDescription desc = configurations.getTableDescription(tableInfo             .getOrgName());       List<NameNodeHolder> nameNodes = desc.getNameNodes();      Function func = desc.getFunction();//分库分表函数,本质就是获取table节点中namenode节点的序号     for (Map<String, Object> item : parameters) {           checkParameters(item, batchItem);         int i = func.execute(nameNodes.size(), item);            indexs.add(i);        }

       if (indexs.size() > 0) {           AnalyzeResult analyzeResult = batchItem.getAnalyzeResult();          HavingInfo havingInfo = analyzeResult.getHavingInfo();           if (havingInfo != null) {                AnalyzerCallback callback = havingInfo.getCallback();                if (callback != null) {                  callback.call();              }         }     }     if ((!batchItem.getAnalyzeResult().getAppendResultColumns().isEmpty() || batchItem                .getAnalyzeResult().getLimit() != null) && indexs.size() > 1) {// 存在limit或者avg等聚集函数,需要重新生成sql         Collection<AnalyzerCallback> analyzerCallbacks = batchItem                 .getAnalyzeResult().getAnalyzerCallbacks();           if (batchItem.getAnalyzeResult().getLimit() != null) {               SqlValueItem limitItem = batchItem.getAnalyzeResult()                        .getLimit();              SqlValueItem offsetItem = batchItem.getAnalyzeResult()                       .getOffset();             if(offsetItem==null){                   offsetItem=new SqlValueItem();                   offsetItem.setValue(0);               }             if (limitItem.getParameterIndex() > 0                      && offsetItem.getParameterIndex() > 0) {// limit ?,?                   Integer limitSize = limitItem.getValue()                         + offsetItem.getValue();                 batchItem.getCallback(limitItem.getParameterIndex())                          .setParameter(limitSize);                 batchItem.getCallback(offsetItem.getParameterIndex())                         .setParameter(0);

                   if(limitItem.getParameterIndex() > offsetItem.getParameterIndex()){                        batchItem.getCallback(offsetItem.getParameterIndex())                         .setParameterIndex(limitItem.getParameterIndex());

                      batchItem.getCallback(limitItem.getParameterIndex())                          .setParameterIndex(offsetItem.getParameterIndex());                   }             } else if (limitItem.getParameterIndex() > 0) {// limit 1,?                    Integer limitSize = limitItem.getValue()                         + offsetItem.getValue();                 batchItem.getCallback(limitItem.getParameterIndex())                          .setParameter(limitSize);             } else if (offsetItem.getParameterIndex() > 0) {// limit ?,10                  batchItem.getCallback(offsetItem.getParameterIndex())                         .setParameter(0);             }         }         for (AnalyzerCallback callback : analyzerCallbacks) {             callback.call();          }     } else {// 在单库路由的情况下,如果检测到是limit ?,?,就置换Parameter顺序         SqlValueItem limitItem = batchItem.getAnalyzeResult()                    .getLimit();          SqlValueItem offsetItem = batchItem.getAnalyzeResult()                   .getOffset();

           if(limitItem !=null && offsetItem !=null &&                     limitItem.getParameterIndex() > offsetItem.getParameterIndex()){

             batchItem.getCallback(offsetItem.getParameterIndex())                 .setParameterIndex(limitItem.getParameterIndex());

              batchItem.getCallback(limitItem.getParameterIndex())                  .setParameterIndex(offsetItem.getParameterIndex());           }     }     for (Integer i : indexs) {// 生成target         NameNode nameNode = configurations.getNameNode(                  tableInfo.getOrgName(), i);           DefaultRouteTarget target = this.createTarget(batchItem, nameNode, tableInfo);           targetSet.add(target);        }

     for (RouteTarget item : targetSet) {          DefaultRouteTarget target = (DefaultRouteTarget) item;           SqlExecuteInfo info = new SqlExecuteInfo();          info.setCallbacks(new LinkedHashSet<ParameterCallback<?>>(batchItem                   .getCallbacks()));

          if (desc.isDifferentName()) {             info.setExecuteSql(configurations.getGenerator().generate(                        (NameNodeHolder) target.getNameNode(),                        batchItem.getAnalyzeResult()));           } else if ((!batchItem.getAnalyzeResult().getAppendResultColumns().isEmpty() || batchItem                 .getAnalyzeResult().getLimit() != null) && nameNodes.size() > 1) {// 存在limit或者avg等聚集函数,需要重新生成sql,必须要超过1个路由结果              info.setExecuteSql(configurations.getLimitAvgGenerator()                      .generate((NameNodeHolder) target.getNameNode(),                              batchItem.getAnalyzeResult()));           } else {              info.setExecuteSql(batchItem.getSql());           }         target.setExecuteInfo(info);      }     return targetSet; }

(3)SimpleExecutor 和 HandlerFactory:

根据StatementContext的RouteTarget(路由数据),

新建事务并获取数据库连接, 实际执行JDBC curd操作的类.

兴趣点:发现doUpdate的时候有用同步工具类:

CyclicBarrier barrier = new CyclicBarrier(n);



@SuppressWarnings({ "rawtypes", "unchecked" })public class SimpleExecutor implements Executor {   static Logger logger = LoggerFactory.getLogger(SimpleExecutor.class);    static final ExecuteHandler<Integer> deleteHandler = new DeleteExecuteHandler();   static final ExecuteHandler<Integer> insertHandler = new InsertExecuteHandler();   static final ExecuteHandler<Integer> updateHandler = new UpdateExecuteHandler();   static final ExecuteHandler<ResultSet> queryHandler = new QueryExecuteHandler();

 @Override    public Object execute(StatementContext context, ExecuteCallback callback)         throws SQLException {

       switch (context.getCurrentBatch().getAnalyzeResult().getStatementType()) {        case SELECT:          return this.doQuery(context, callback);       case INSERT:      case UPDATE:      case DELETE:          return doUpdate(context, callback);       default:          break;        }     return null;  }

   ExecuteHandler<?> getHandler(StatementType statementType) {     switch (statementType) {      case SELECT:          return queryHandler;      case INSERT:          return insertHandler;     case UPDATE:          return updateHandler;     case DELETE:          return deleteHandler;     default:          break;        }     return null;  }...

5.集成Mybatis:

因为Mybatis获取连接是通过PooledDataSource或UnpooledDataSource获取的,所以写个插件:包装下DataSource,把oceanus的connentionWrap包装进去即可实现整合。

oceanus-58总体框架理解相关推荐

  1. ROS探索总结(一)(二)(三):ROS总体框架 ROS总体框架 ROS新手教程

    ROS探索总结(一)--ROS简介 一.历史 随着机器人领域的快速发展和复杂化,代码的复用性和模块化的需求原来越强烈,而已有的开源机器人系统又不能很好的适应需求.2010年Willow Garage公 ...

  2. 《机械制造业智能工厂规划设计》——第3章 机械制造业智能工厂的总体框架 3.1 智能制造的通用定义和特征...

    第3章 机械制造业智能工厂的总体框架 3.1 智能制造的通用定义和特征 1.智能制造的定义和内涵 智能制造系统(Intelligent Manufacturing System,IMS)是一种由智能机 ...

  3. 从零开始搭建ROS移动机器人系列之(一)预备知识及总体框架

    " 笔者2020年初次接触ROS,2021年参加工作以后,愈发对ROS产生浓厚的兴趣,渴望拥有一台ROS机器人,淘宝上一搜再搜,发现有很多现成的产品,但是价格属实让人望而却步,遂产生了自己搭 ...

  4. 从Netflix的Hystrix框架理解服务熔断和服务降级

    本文讲的是从Netflix的Hystrix框架理解服务熔断和服务降级,伴随着微服务架构被宣传得如火如荼,一些概念也被推到了我们面前,其实大多数概念以前就有,但很少被提的这么频繁.想起有人总结的一句话, ...

  5. 城市大脑标准体系与评价指标总体框架研究

    来源:城市大脑全球标准研究组 根据城市大脑标准的前期研究和中国指挥与控制学会(CICC)<城市大脑建设规范>标准启动会的专家意见,形成城市大脑标准体系与评价指标总体框架(如图1所示),供各 ...

  6. 企业档案信息化规划总体框架

    按照<中华人民共和国档案法><企业档案管理规定><企业档案工作规范><企业数字档案馆(室)建设指南>等政策文件要求,企业档案信息化建设应从基础设施体系. ...

  7. 蜂鸟E203学习笔记(二)--蜂鸟E203总体框架

    蜂鸟E203总体框架 蜂鸟E203处理器系统如下图所示 一.蜂鸟E203处理器核设计总览和顶层 1.1 蜂鸟E203处理器核的设计理念 模块化和可重用性:将处理器分成几个主体模块,每个单元之间的接口简 ...

  8. ZigBee Silicon Labs/Ember EFR32MG/EM357 1.1 总体框架

    开启ZigBee新篇章,陆续更新,欢迎关注~ 第一章 总体框架 (已发布 V1 20180201)ZigBee Silicon Labs/Ember EFR32MG/EM357 1.1 总体框架(&l ...

  9. 理想智慧社区建设的总体框架

    导读: 理想智慧社区是未来现代化城市的细胞,也是未来城市的缩影,但它相较城市范围较小,便于试点.理想智慧社区建设为社区有机更新指引了一个新的方向,重点关注人民美好生活需要.基层现代化治理和商业服务模式 ...

最新文章

  1. python 文字转语音
  2. Qt 控制watchdog app hacking
  3. js实现语音播报功能
  4. 棋牌游戏服务器架构: 详细设计(二) 应用层设计
  5. 4月21日会议总结(整理—祁子梁)
  6. 修改tomcat服务器图标,修改tomcat小猫图标,设置项目的favicon图标
  7. freemarker中运算符_freemarker常见语法大全
  8. tornado异步客户端(Future)
  9. 记一次css载入指定url失败
  10. leetcode 240. 搜索二维矩阵 II
  11. struts2中的action获取web资源
  12. C语言———求”完数“
  13. linux怎么下载ftp文件夹,命令行 - 如何在Linux上通过FTP递归下载文件夹
  14. java实习收获与体会_java实习心得体会.doc
  15. 中国历代更改重复地名及其现实意义
  16. 【渗透测试笔记】之【Cobalt Strike小技巧——后台挂起CS服务端】
  17. cubic与bbr性能实测
  18. Es6常见面试题必看!
  19. 一个人到过的12个国家,45座城市
  20. 最小二乘法、加权最小二乘法——直线拟合

热门文章

  1. set_input_delay/set_output_delay
  2. Percona-toolkit工具详解
  3. 使用cordova + vue搭建混合app框架
  4. Node 开发npm脚手架(类似vue-cli)
  5. 【程序】STM32H743ZI单片机驱动DP83848以太网PHY芯片,移植lwip 2.1.3协议栈,并加入网线热插拔检测的功能
  6. linux 中的DNS服务
  7. 李克用置酒三垂冈赋——刘翰(清)
  8. TextView显示省略号问题
  9. linux升级n卡驱动,Centos 7 更新 NVIDIA 驱动
  10. phpstorm破解后,运行一段时间后突然有提示没有破解.