激情久久久_欧美视频区_成人av免费_不卡视频一二三区_欧美精品在欧美一区二区少妇_欧美一区二区三区的

服務(wù)器之家:專注于服務(wù)器技術(shù)及軟件下載分享
分類導(dǎo)航

PHP教程|ASP.NET教程|Java教程|ASP教程|編程技術(shù)|正則表達(dá)式|C/C++|IOS|C#|Swift|Android|VB|R語言|JavaScript|易語言|vb.net|

服務(wù)器之家 - 編程語言 - Java教程 - Mybatis框架及原理實例分析

Mybatis框架及原理實例分析

2020-12-10 14:31atheva Java教程

這篇文章主要介紹了Mybatis框架及原理實例分析,需要的朋友可以參考下

摘要

本篇文章只是個人閱讀mybatis源碼總結(jié)的經(jīng)驗或者個人理解mybatis的基本輪廓,作為拋磚引玉的功能,希望對你有幫助,如果需要深入了解細(xì)節(jié)還需親自去閱讀源碼。

mybatis基本架構(gòu)

mybatis的源碼應(yīng)該算是比較容易閱讀的,首先mybatis核心功能就是執(zhí)行sql語句,但在其基礎(chǔ)上又有許多增強(qiáng)的地方(動態(tài)sql,orm等)??匆粋€框架的時候,第一步是對整個框架有一個大體的了解。例如mybatis,我們可以從初始化到完成一個sql請求為主線,看一下涉及了哪些類。我個人總結(jié)了一下,mybatis的框架主要的核心類有4個

Mybatis框架及原理實例分析

configuration

configuration就是用于解析、保存、處理mybatis的配置內(nèi)容,包括了

  • mybatis基本配置,例如支持?jǐn)?shù)據(jù)庫中的字段支持下標(biāo)轉(zhuǎn)駝峰mapunderscoretocamelcase=true等等,參看mybatis配置說明
  • sqlmapper管理,也就是通過xml或者注解寫的一些sql映射。相關(guān)的類可以查看源碼中mappedstatement類。
  • 創(chuàng)建類,configuration還有一些創(chuàng)建類的功能,例如executor、statementhandler。這個2個類后面還會說到

小節(jié)configuration

總結(jié)configuration的功能,當(dāng)然,如何讀取和解析相關(guān)文件是configuration中大部分代碼做的事。這些都是為了準(zhǔn)備后面mybatis運(yùn)行的基本條件。configuration中創(chuàng)建類是因為創(chuàng)建的這些類都依賴于configuration(但這樣做數(shù)據(jù)和邏輯沒有做到分離)。

sqlsession

sqlsession可能是mybatis中我們最常用的類,其實他是一個門面類,直接對外提供服務(wù)

?
1
2
3
4
5
6
7
8
9
public interface sqlsession extends closeable {
 <t> t selectone(string statement);
 <e> list<e> selectlist(string statement, object parameter);
 int delete(string statement);
 void rollback();
 void commit();
 ...
 
}

這些方法都是直接提供給外部調(diào)用的。看到這些方法是不是很親切。(我個人在看源碼的時候看到一些自己用過的一些類或方法的時候都有種莫名的親近感。感覺終于和我的認(rèn)知世界有交集了)

sqlsession的創(chuàng)建

sqlsessionfactor是用于創(chuàng)建sqlsession建造者,提供給外部快速創(chuàng)建一個sqlsession。是一個工廠類,而sqlsessionfactor的創(chuàng)建則是由sqlsessionfactorbuilder。

Mybatis框架及原理實例分析

executor

前面說了sqlsession只是一個門面類,executor才是負(fù)責(zé)sql語句執(zhí)行的。因此executor才是整個mybatis核心。executor的實現(xiàn)類有

Mybatis框架及原理實例分析

  • baseexecutor:看名字知道是最基礎(chǔ)executor,其他的executor都和這個類有一定的關(guān)系
  • cachingexecutor:每次查詢的時候會先從緩存中獲取,每次有增刪改的時候會讓緩存失效。cachingexecutor其實是一個代理內(nèi),內(nèi)部代理了baseexecutor(或其子類)。在baseexecutor基礎(chǔ)上增加了緩存操作。

相關(guān)類

我們看一個executor參數(shù)最多的一個方法

?
1
<e> list<e> query(mappedstatement ms, object parameter, rowbounds rowbounds, resulthandler resulthandler, cachekey cachekey, boundsql boundsql) throws sqlexception;

這些類都對執(zhí)行sql有一定關(guān)系

mappedstatement

具體點來理解就是我們定義的sql映射語句,例如我們xml定義的:

?
1
2
3
4
<select id="selectcountbypath" parametertype="java.lang.string" resulttype="java.lang.long">
 select count(1) from config
 where path = #{path}
</select>

paramter

這個就是傳遞給sql映射的參數(shù),用于生成和填充動態(tài)sql語句

rowbound

限定一次查詢數(shù)據(jù)量,類很簡單,看代碼就明白,不多說

?
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
public class rowbounds {
 public static final int no_row_offset = 0;
 public static final int no_row_limit = integer.max_value;
 public static final rowbounds default = new rowbounds();
 private int offset;
 private int limit;
 public rowbounds() {
 this.offset = no_row_offset;
 this.limit = no_row_limit;
 }
 public rowbounds(int offset, int limit) {
 this.offset = offset;
 this.limit = limit;
 }
}

resulthandler

這個和本地緩存有關(guān),用于保存一個查詢語句的緩存對象,下次有相同的查詢語句的時候就會先嘗試從本地緩存中獲取。 注意:

,mybatis有2級緩存,第一級是cachingexecutor,第二級緩存就是mybatis的本地緩存,也就是和resulthandler

緩存失效策略是和一級緩存一樣,任何增刪改都會清空本地緩存

cachekey

一個查詢語句的在本地緩存中的key,根據(jù)sql語句,參數(shù)等等組成

boundsql

這個對象就是本次實際需要執(zhí)行的sql語句有關(guān)的信息,

?
1
2
3
4
5
6
7
public class boundsql {
 private string sql;
 private list<parametermapping> parametermappings;
 private object parameterobject;
 private map<string, object> additionalparameters;
 private metaobject metaparameters;
 ...

如果說parameter參數(shù)是實際傳入的參數(shù),那么boundsql就是根據(jù)傳入?yún)?shù)進(jìn)行相關(guān)解析后的結(jié)果。他的創(chuàng)建在mappedstatement中,根據(jù)parameter和當(dāng)前執(zhí)行mappedstatement生成

?
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
public boundsql getboundsql(object parameterobject) {
 boundsql boundsql = sqlsource.getboundsql(parameterobject);
 list<parametermapping> parametermappings = boundsql.getparametermappings();
 if (parametermappings == null || parametermappings.isempty()) {
  boundsql = new boundsql(configuration, boundsql.getsql(), parametermap.getparametermappings(), parameterobject);
 }
 // check for nested result maps in parameter mappings (issue #30)
 for (parametermapping pm : boundsql.getparametermappings()) {
  string rmid = pm.getresultmapid();
  if (rmid != null) {
  resultmap rm = configuration.getresultmap(rmid);
  if (rm != null) {
   hasnestedresultmaps |= rm.hasnestedresultmaps();
  }
  }
 }
 return boundsql;
}

interceptor

mybatis提供了interceptor用于在執(zhí)行executor之前進(jìn)行一些操作,mybatis是怎么使用interceptor。其實就是在創(chuàng)建executor時候,會

?
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
public executor newexecutor(transaction transaction, executortype executortype) {
 executortype = executortype == null ? defaultexecutortype : executortype;
 executortype = executortype == null ? executortype.simple : executortype;
 executor executor;
 if (executortype.batch == executortype) {
  executor = new batchexecutor(this, transaction);
 } else if (executortype.reuse == executortype) {
  executor = new reuseexecutor(this, transaction);
 } else {
  executor = new simpleexecutor(this, transaction);
 }
 if (cacheenabled) {
  executor = new cachingexecutor(executor);
 }
 //看這里?。?!
 executor = (executor) interceptorchain.pluginall(executor);
 return executor;
 }

這里主要是通過jdk動態(tài)代理實現(xiàn)的

?
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
public class plugin implements invocationhandler {
 ...
 public static object wrap(object target, interceptor interceptor) {
 map<class<?>, set<method>> signaturemap = getsignaturemap(interceptor);
 class<?> type = target.getclass();
 class<?>[] interfaces = getallinterfaces(type, signaturemap);
 if (interfaces.length > 0) {
  return proxy.newproxyinstance(
   type.getclassloader(),
   interfaces,
   new plugin(target, interceptor, signaturemap));
 }
 return target;
 }
 
 ...
 @override
 public object invoke(object proxy, method method, object[] args) throws throwable {
 try {
  set<method> methods = signaturemap.get(method.getdeclaringclass());
  if (methods != null && methods.contains(method)) {
  return interceptor.intercept(new invocation(target, method, args));
  }
  return method.invoke(target, args);
 } catch (exception e) {
  throw exceptionutil.unwrapthrowable(e);
 }
 }

這樣在調(diào)用executor的時候就會先判斷是否滿足interceptor的執(zhí)行條件,滿足則會先執(zhí)行intercepter#intercept()方法

最底層的handler

要說直接和jdbc打交道的就是各種handler類,例如

  • statementhandler: 處理java.sql.statement
  • parameterhandler: 向preparedstatement中設(shè)置參數(shù)
  • resultsethandler:處理sql執(zhí)行結(jié)果,并轉(zhuǎn)換成指定的類對象 上面的這些其實都不復(fù)雜,所以代碼還是比較好理解的

transaction

每個executor生成的時候都會把transaction傳入,在baseexecutor中transaction是其成員變量,那transaction的作用是什么呢?

?
1
2
3
4
5
6
7
public interface transaction {
 connection getconnection() throws sqlexception;
 void commit() throws sqlexception;
 void rollback() throws sqlexception;
 void close() throws sqlexception;
 integer gettimeout() throws sqlexception;
}

其實之前一直都沒提到過connect誰來管理,這里可以看出來,transaction負(fù)責(zé)了connection的獲取,以及對這次connect的提交和回滾等操作。這個類也是比較好理解的。executor的commit或者rollback最后都是調(diào)用transaction的

總結(jié)

可以看出,mybatis的源碼是比較容易閱讀的(相對于spring等)。上面介紹了框架中的一些核心類,但是很多細(xì)節(jié)的地方值得我們?nèi)ド钔?。這個就需要我們能沉下來好好閱讀代碼。

原文鏈接:http://www.cnblogs.com/lizo/p/7281441.html

延伸 · 閱讀

精彩推薦
主站蜘蛛池模板: 一级大黄毛片免费观看 | 精品国产一区二区在线 | 国产精品久久久久免费视频 | 久久久噜噜噜久久熟有声小说 | 国产深夜福利视频在线播放 | 永久av在线免费观看 | 国产中文99视频在线观看 | 日本教室三级在线看 | 中文字幕综合在线观看 | 欧美日韩亚洲一区二区三区 | 欧美日韩精品中文字幕 | 欧美一级在线免费 | 性猛aa久久久 | 九九热视频在线免费观看 | 九九视屏 | 欧美精品一区二区久久 | 欧美日韩高清在线观看 | 国产亚洲精品久久午夜玫瑰园 | 黄色免费在线网站 | 露脸各种姿势啪啪的清纯美女 | 中国a级黄色片 | h视频免费在线观看 | 中文字幕在线观看网址 | 久久综合综合久久 | 日本一区二区三区精品 | 黄色av网站在线观看 | 精品欧美一区二区精品久久 | 91精品国产一区二区三区动漫 | 一级网站 | 亚洲尻逼视频 | 欧美高清一级片 | 一级黄色免费大片 | 日本久久精品视频 | 久久国产精品久久久久久电车 | 久久色网站| 亚洲精品永久视频 | 看毛片电影 | 亚洲一区在线免费视频 | 久久久久亚洲视频 | www.成人在线| 在线观看日韩电影 |