范文健康探索娱乐情感热点
投稿投诉
热点动态
科技财经
情感日志
励志美文
娱乐时尚
游戏搞笑
探索旅游
历史星座
健康养生
美丽育儿
范文作文
教案论文

深入了解Mybatis架构设计

  架构设计
  我们可以把Mybatis的功能架构分为三层: API接口层:提供给外部使用的接口API,开发人员通过这些本地API来操纵数据库。接口层一接收到调用请求就会调用数据处理层来完成具体的数据处理。
  Mybatis和数据库的交互有两种方式: 使用传统的Mybatis提供API 使用Mapper代理的方式 数据处理层:负责具体的SQL查找、SQL解析、SQL执行和执行结果映射处理等。他主要的目的是根据调用的请求完成一次数据库操作。 基础支撑层:负责最基础的功能支撑,包括连接管理、事务管理、配置加载和缓存处理,这些都是共用的东西,将他们抽取出来最为基础组件。为上层的数据处理层提供最基础的支撑。
  Mybatis主要构件
  总体流程: 加载配置并初始化
  配置来源于两个地方,一个是配置文件(conf.xml,mapper*.xml),一个是java代码中的注解,将配置文件内容封装到Configuration,将sql的配置信息加载成为一个mappedstatement对象,存储在内存中。
  2. 接收调用请求
  触发条件:调用Mybatis提供的API
  传入参数:为SQL的ID和传入的参数
  将请求传递给下层的请求处理层进行处理 处理操作请求 根据SQL的ID查找对应的MappedStatement对象 根据传入参数对象解析,得到最终要执行的SQL和执行传入参数 获取数据库连接,将最终SQL语句和参数给到数据库执行,并得到执行结果 根据MappedStatement对象中的结果映射配置对得到的执行结果进行转换处理,并得到最终的处理结果 释放连接资源 返回处理结果 Mybatis缓存
  Mybatis有一级缓存和二级缓存。Mybatis收到查询请求后首先会查询二级缓存,若二级缓存未命中,再去查询一级缓存,一级缓存没有,再查询数据库。
  一级缓存 public  List query(MappedStatement ms, Object parameter, RowBounds rowBounds, ResultHandler resultHandler, CacheKey key, BoundSql boundSql) throws SQLException {     ErrorContext.instance().resource(ms.getResource()).activity("executing a query").object(ms.getId());     if (closed) {       throw new ExecutorException("Executor was closed.");     }     if (queryStack == 0 && ms.isFlushCacheRequired()) {       clearLocalCache();     }     List list;     try {       queryStack++;       //从localCache缓存里查数据,没有就去查数据库       list = resultHandler == null ? (List) localCache.getObject(key) : null;       if (list != null) {         handleLocallyCachedOutputParameters(ms, key, parameter, boundSql);       } else {         list = queryFromDatabase(ms, parameter, rowBounds, resultHandler, key, boundSql);       }     } finally {       queryStack--;     }     if (queryStack == 0) {       for (DeferredLoad deferredLoad : deferredLoads) {         deferredLoad.load();       }       // issue #601       deferredLoads.clear();       if (configuration.getLocalCacheScope() == LocalCacheScope.STATEMENT) {         // issue #482         clearLocalCache();       }     }     return list;   }
  这个localCache是BaseExecutor里面的一个属性 public abstract class BaseExecutor implements Executor {     protected PerpetualCache localCache;
  PerpetualCache类 public class PerpetualCache implements Cache {    private final String id;    private Map cache = new HashMap();    public PerpetualCache(String id) {     this.id = id;   }    @Override   public String getId() {     return id;   }    @Override   public int getSize() {     return cache.size();   }    @Override   public void putObject(Object key, Object value) {     cache.put(key, value);   }    @Override   public Object getObject(Object key) {     return cache.get(key);   }
  二级缓存
  启用二级缓存步骤: 开启cacheEnabled(默认打开)    需要在二级缓存的Mapper配置文件中加入  注意,二级缓存要想生效,必须要调用sqlSession.commit或close方法  public  List query(MappedStatement ms, Object parameterObject, RowBounds rowBounds, ResultHandler resultHandler, CacheKey key, BoundSql boundSql)       throws SQLException {     Cache cache = ms.getCache();     if (cache != null) {       flushCacheIfRequired(ms);       if (ms.isUseCache() && resultHandler == null) {         ensureNoOutParams(ms, parameterObject, boundSql);         @SuppressWarnings("unchecked")         List list = (List) tcm.getObject(cache, key);         if (list == null) {           list = delegate. query(ms, parameterObject, rowBounds, resultHandler, key, boundSql);           tcm.putObject(cache, key, list); // issue #578 and #116         }         return list;       }     }     return delegate. query(ms, parameterObject, rowBounds, resultHandler, key, boundSql);   }
  注意Cache cache = ms.getCache();,这个cache是从MappedStatement中获取到的,由于MappedStatement存在全局配置中,可以多个CachingExecutor获取到,这样就会出现线程安全问题。除此之外,若不加以控制,多个事务共用一个缓存实例,会导致脏读的存在。
  那么mybatis是怎么解决脏读的呢?借用了上面的tcm这个变量,也就是TransactionalCacheManager类来解决的。
  TransactionalCacheManager类维护了Cache,TransactionalCache的关系,真正的数据还是交由TransactionalCache处理的。
  结构如图:
  public class TransactionalCacheManager {    private final Map transactionalCaches = new HashMap();    public void clear(Cache cache) {     getTransactionalCache(cache).clear();   }    public Object getObject(Cache cache, CacheKey key) {     return getTransactionalCache(cache).getObject(key);   }      public void putObject(Cache cache, CacheKey key, Object value) {     getTransactionalCache(cache).putObject(key, value);   }    public void commit() {     for (TransactionalCache txCache : transactionalCaches.values()) {       txCache.commit();     }   }    public void rollback() {     for (TransactionalCache txCache : transactionalCaches.values()) {       txCache.rollback();     }   }    private TransactionalCache getTransactionalCache(Cache cache) {     TransactionalCache txCache = transactionalCaches.get(cache);     if (txCache == null) {       txCache = new TransactionalCache(cache);       transactionalCaches.put(cache, txCache);     }     return txCache;   }  }
  接下来看一下TransactionalCache的代码 public class TransactionalCache implements Cache {    private static final Log log = LogFactory.getLog(TransactionalCache.class);    // 真正的缓存对象   private final Cache delegate;   private boolean clearOnCommit;   //在事务被提交前,所有从数据库中查询的结果将缓存在此集合中   private final Map entriesToAddOnCommit;   //在事务被提交前,当缓存未命中时,CacheKey 将会被存储在此集合中   private final Set entriesMissedInCache;    public TransactionalCache(Cache delegate) {     this.delegate = delegate;     this.clearOnCommit = false;     this.entriesToAddOnCommit = new HashMap();     this.entriesMissedInCache = new HashSet();   }    @Override   public String getId() {     return delegate.getId();   }    @Override   public int getSize() {     return delegate.getSize();   }    @Override   public Object getObject(Object key) {     // issue #116     //获取缓存的时候从delegate里获取的     Object object = delegate.getObject(key);     if (object == null) {       //缓存未命中,将key存入entriesMissedInCache.       entriesMissedInCache.add(key);     }     // issue #146     if (clearOnCommit) {       return null;     } else {       return object;     }   }    @Override   public ReadWriteLock getReadWriteLock() {     return null;   }    @Override   public void putObject(Object key, Object object) {     //put的时候只是将数据库的数据放入到了entriesToAddOnCommit     entriesToAddOnCommit.put(key, object);   }    @Override   public Object removeObject(Object key) {     return null;   }    @Override   public void clear() {     clearOnCommit = true;     entriesToAddOnCommit.clear();   }    public void commit() {     if (clearOnCommit) {       delegate.clear();     }     //刷新未缓存的结果到delegate中去     flushPendingEntries();     reset();   }    public void rollback() {     unlockMissedEntries();     reset();   }    private void reset() {     clearOnCommit = false;     entriesToAddOnCommit.clear();     entriesMissedInCache.clear();   }    private void flushPendingEntries() {     for (Map.Entry entry : entriesToAddOnCommit.entrySet()) {       delegate.putObject(entry.getKey(), entry.getValue());     }     for (Object entry : entriesMissedInCache) {       if (!entriesToAddOnCommit.containsKey(entry)) {         delegate.putObject(entry, null);       }     }   }    private void unlockMissedEntries() {     for (Object entry : entriesMissedInCache) {       try {         delegate.removeObject(entry);       } catch (Exception e) {         log.warn("Unexpected exception while notifiying a rollback to the cache adapter."             + "Consider upgrading your cache adapter to the latest version.  Cause: " + e);       }     }   }  }
  我们存储二级缓存的时候是放入到TransactionalCache.entriesToAddOnCommit这个map中,但是每次查询的时候是从delegate查询的,所以这个二级缓存查询数据库后,缓存是没有立刻生效的。只有当执行了sqlSession的commit或close方法后,它会调用到tcm的commit,在调用到transactionlCache的commit,刷新缓存到delegate了。
  总结: 二级缓存的设计上,大量运用了装饰器模式,如SynchronizedCache、LoggingCache。 二级缓存实现了Sqlsession之间的缓存数据共享,属于namespace级别 二级缓存的实现由CachingExecutor和一个事务型预缓存TransactionlCache完成。
把家庭电脑变为家庭私有云如何把家庭电脑变成家庭的私有云。本文以本人的老旧主机为例。电脑配置cpuE31231V3主板B85内存8GB显卡GT610硬盘240GSSD一个,500GSSD两个操作系统Wind重回1999元,5nm芯片10bit屏轻薄机身,你们还不买吗?自从华为遭到断货后,手机业务下滑很严重,从仅次于三星手机的全球排名第二,跌到了前五开外了,已经沦为others,国产机小米接棒华为,超越苹果手机成为了排名第二的手机巨头,雷军也在2提倡自然美的自拍手机,这次vivoS10系列又领先行业一个身位说起自拍手机,人们想到的可能是美颜滤镜之类关键词。这在以往,这些都是用户的刚需。不过,现在的年轻人开始追求个性,对千篇一律的美颜,自己都不认识自己的自拍,已经有抵触情绪。vivoS支付宝借呗欠了8万,现在没有能力还,应该怎么办啊?我就来说说一些简单的操作吧。首先欠了支付宝8万,第一,要看你本人有没有还款的意愿。第二,如果你没有还款的意愿只是到纯想知道不还的后果。首先来说说第一种情况,有还款的意愿,那么你能在在京东上买的空调,顺丰的快递这几天心想着买个空调凉快一下,虽说立秋了,但是南方的天气还是燥热,在南方本来就有秋老虎一说。在各个电商平台上找空调,心想京东的东西都不错,加上强子为人比较厚道于是果断在京东下单了一高达540亿美元,特斯拉亚马逊三星都反对,芯片巨头英伟达这单交易会黄吗?美国芯片巨头英伟达想要收购英国芯片设计公司ARM,困难重重。在各国政府审查还悬而未决之时,这起价值540亿美元的收购案又遭到了业内多个大佬的反对。反对的理由显而易见两家把控行业上游7月手机销量排行,荣耀超越小米,重回国内前三荣耀自独立之后,新荣耀的销量一直备受市场关注,人们都想知道脱离华为这棵大树之后,新荣耀是否能够独自撑起销售市场,要知道曾经的荣耀可是手机市场的香饽饽,独立以来,新荣耀先后推出了多款一文看懂字节收购Pico背后的秘密(格局版)前天晚上,警长撰写一文看懂字节收购Pico背后的秘密一文后,相关方公司高层极其重视并向作者提出撤除文章诉求。警长表示理解,同意将文章做删除处理,并于昨日上午删除推文。今天,媒体披露家庭装修路由器和ap面板如何选各自优缺点路由器,信号强,发热低,承载力强,性价比较高,占空间,不美观。ap面板,相比路由器信号较弱,能同时接入的设备较少,受制于散热,网速有一定限制,价格较贵。市面上ap面板多数网友超低价2400入手iPhoneXSMax,只有两个小问题!太值了现在想买个二手iPhone太难了!很容易翻车。网友入手了一台iPhoneXSMax,只花了2400元。但有两个小问题一个是换过电池,一个是换过屏幕!但奇怪的是明明商家告知了换过屏幕配资哪家正规配资炒股正好配资解析小米11Ultra相机迎重大升级众所周知,国产手机影像实力最好的一直都是华为,尤其是华为P系列,但由于今年受到限制,华为P50一直迟迟没有消息,所以现在如果你问我哪一款高端旗舰机拍照最好?,我会毫无犹豫的推荐你选
江苏科技创新专项资金项目即将启动光伏在内1月10日,江苏省科学技术厅发文称,去年11月上旬,省科技厅面向全省发布了2021年度省碳达峰碳中和科技创新专项资金项目指南。目前,省科技厅已完成首批项目的组织申报项目受理专家评审交通运输部将引导19。61亿元社会资金投入交通运输科技研发来源人民网原创稿人民网北京1月10日电(记者王连香)近日,交通运输部公布2021年度交通运输行业重点科技项目清单,共有288个项目入选,将引导19。61亿元社会资金投入交通运输科技FITURE携手天美健康,用交互科技助推全民健身发展中国青年报客户端讯(中青报中青网记者谢宛霏)近日,智能健身独角兽生活方式品牌FITURE与天美工作室群旗下专注运动健康领域的子品牌天美健康,举办了天美健康局开局先开练战略合作发布会千元高性价比机型?说到高性价比的手机,相信不少的消费者会想起小米旗下的子品牌红米,作为较早创立的一家子品牌厂商,较早地提出了性价比这个口号的品牌,从此让消费者们记住了这个独具性价比的品牌,让我们的选通网只是农村地区互联网建设的第一步新闻随笔作者陈城近日,中国互联网络信息中心发布了第48次中国互联网络发展状况统计报告(以下简称报告)。该报告显示,截至2021年6月,我国农村网民规模为2。97亿,农村地区互联网普戏说中国互联网5大巨头宝哥说这些看法不一定正确,但一定好玩。本文概述当企业做大做强之后,人们对他们的看法,也会逐渐变得复杂割裂,甚至措辞激烈。当然,这些看法不一定正确,但一定好玩。今天,我们将对阿里腾讯EUV也困不住中国芯了?新方向被确认,中科院立功了本文原创,禁止搬运和抄袭,违者必究!硅基是国际主流的芯片材料,在长达半个世纪的发展历程中,市面上所有的通用CPU,GPU等处理器都是以硅作为核心材料。但是摩尔定律即将到达极限,这时全球连线中国西部普通消费者沉浸式体验5G创新应用视频加载中8月初,在地处中国西北的甘肃省兰州市,由中国移动通信集团甘肃有限公司投资建设的甘肃5G联合创新中心正式建成投用。这个面积约1500平方米的创新中心不仅向普通用户系统展示了家里的WIFI信号时断时续,工作人员真正来检查说没毛病,是为什么呢?本行业问题,我来回答。家里wifi信号时段时续,工作人员来检查的时候说没毛病,这里可以比较肯定的是你说的工作人员是三大运营商宽带的装机员,他们不管无线,只负责光猫部分,因为这段没毛我与收音机会这样厮守下去最近迷上了网络收音机,听书听小说用朝元,听国际电台用海弦,有人说这叫傻瓜机简单有效,有人说这东西可能会昙花一现还会持币观望,还有人说老金这是掉进网络收音机堆里无法自拔了吗?海弦wr苹果iOS15Beta7体验5项更新,3个修复和小问题,使用稳定大家好,我是氪哥。本想更拿iPhone12做最新一期的测试,但是无奈一共要做三个系统才有参考性(iOS14。7。115Beta两个),所以还是没有那么快出结果。这期iOS15Bet