MyBatis源碼分析(05)執(zhí)行查詢SQL

前面的獲取對象的過程基本都debug完了痘昌,下面看最后一行:

String name = mapper.selectNameById(1);

也就是執(zhí)行SQL語句的具體過程。





下面從SQL語句的執(zhí)行開始debug:

1入偷、String name = mapper.selectNameById(1);

我們自定義的接口UserMapper是個接口,沒有實(shí)現(xiàn)類脖岛,前面分析獲取mapper時我們知道隧出,mybatis會為mapper類生成代理類,生成代理類的方法是使用MapperProxyFactory工廠類生成,代理的類其實(shí)就是MapperProxy宿饱,所以我們要看下一步的執(zhí)行過程就要進(jìn)入這個類進(jìn)行查看熏瞄,

1、String name = mapper.selectNameById(1);

2谬以、org.apache.ibatis.binding.MapperProxy#invoke

其中第一個if判斷?if (Object.class.equals(method.getDeclaringClass()))? 强饮,這個MapperProxy就是一個InvocationHandler(他的作用是jdk創(chuàng)建動態(tài)代理時用的,沒印象的可以復(fù)習(xí)一下)为黎,也就是我們會根據(jù)當(dāng)前的接口創(chuàng)建一個這個接口的動態(tài)代理對象邮丰,使用動態(tài)代理對象再利用反射調(diào)用實(shí)際對象的目標(biāo)方法。

然而動態(tài)代理對象里面的方法都是Interface規(guī)定的铭乾。但是動態(tài)代理對象也能調(diào)用比如toString(),hashCode()等這些方法呀剪廉,這些方法是所有類從Object繼承過來的。

所以這個判斷的根本作用就是炕檩,如果利用動態(tài)代理對象調(diào)用的是toString斗蒋,hashCode,getClass等這些從Object類繼承過來的方法,就直接反射調(diào)用笛质。如果調(diào)用的是接口規(guī)定的方法泉沾。我們就用MapperMethod來執(zhí)行。所以這個判斷是十分必要的妇押。

繼續(xù)看下面的方法爆哑,判斷出不是Object的方法,是接口的方法舆吮,所以執(zhí)行下面的代碼揭朝,從cachedMapperMethod中獲取要執(zhí)行的方法:

1、String name = mapper.selectNameById(1);

2色冀、org.apache.ibatis.binding.MapperProxy#invoke

3潭袱、org.apache.ibatis.binding.MapperProxy#cachedMapperMethod

這是個典型的從緩存中獲取方法對象的代碼,如果緩存中沒有锋恬,就新建并加入緩存屯换,最后返回這個方法,methodCache對象是一個map与学,存儲了創(chuàng)建過的方法對象彤悔,創(chuàng)建的方式是根據(jù)接口,方法和配置對象進(jìn)行創(chuàng)建索守。到這里我們就獲取了我們實(shí)際要執(zhí)行的方法的對象了晕窑。

現(xiàn)在我們回來繼續(xù)看第二步,回到org.apache.ibatis.binding.MapperProxy#invoke方法中卵佛,

最后一行代碼return中執(zhí)行的杨赤,就是真正操作數(shù)據(jù)庫的方法敞斋。我們繼續(xù)看下一步:

1、String name = mapper.selectNameById(1);

2疾牲、org.apache.ibatis.binding.MapperProxy#invoke

3植捎、org.apache.ibatis.binding.MapperProxy#cachedMapperMethod

4、org.apache.ibatis.binding.MapperMethod#execute

進(jìn)入這個方法可以看到阳柔,內(nèi)容很豐富焰枢,開始是一個判斷語句塊,判斷當(dāng)前的操作是什么類型舌剂,我們通過idea來看一下正在執(zhí)行的是什么類型:

如果是增刪改的話济锄,執(zhí)行方式比較一致和簡單,

準(zhǔn)備好參數(shù)然后去執(zhí)行架诞,本次執(zhí)行的是查詢操作拟淮,所以我們主要看下面的SELECT:

查詢操作通過判斷返回的類型,執(zhí)行對應(yīng)的方法谴忧,前面幾種是比較經(jīng)典的返回類型很泊,如果都不滿足,就會執(zhí)行else內(nèi)的方法沾谓,本次的selectNameById方法執(zhí)行的就是else中的內(nèi)容:

第一行是轉(zhuǎn)換參數(shù)為SQL命令中的形式委造,下面這一行是關(guān)鍵,真正執(zhí)行的是sqlSession.selectOne方法均驶,我們在前面討論獲取sqlSession對象的源碼的時候昏兆,查看了SqlSession類中的方法,這是其中一個妇穴。傳入的第一個參數(shù)就是方法:

第二個就是參數(shù)爬虱,下面我進(jìn)入這個方法,查看流程:

1腾它、String name = mapper.selectNameById(1);

2跑筝、org.apache.ibatis.binding.MapperProxy#invoke

3、org.apache.ibatis.binding.MapperProxy#cachedMapperMethod

4瞒滴、org.apache.ibatis.binding.MapperMethod#execute

5曲梗、org.apache.ibatis.session.defaults.DefaultSqlSession#selectOne(java.lang.String, java.lang.Object)

我們在使用mybatis的時候,用的是官方文檔建議的方法妓忍,獲取mapper對象虏两,使用mapper對象執(zhí)行我們自定義的數(shù)據(jù)庫操作方法。官方文檔上還有另一種調(diào)用方法:

就是直接調(diào)用sqlSession中的方法世剖,上面圖片例子中的兩個參數(shù)就是我們前面的過程在組合的參數(shù)定罢,也就是說獲取mapper對象執(zhí)行方法最終的過程也是執(zhí)行sqlSession中的內(nèi)容,和上面這種方法殊途同歸搁廓。我們繼續(xù)來看selectOne中的內(nèi)容引颈,selectOne最終的執(zhí)行過程也是執(zhí)行selectList查詢一個列表耕皮,然后獲取列表中的第一個元素境蜕,繼續(xù)看selectList方法:

1蝙场、String name = mapper.selectNameById(1);

2勇皇、org.apache.ibatis.binding.MapperProxy#invoke

3慨仿、org.apache.ibatis.binding.MapperProxy#cachedMapperMethod

4钦睡、org.apache.ibatis.binding.MapperMethod#execute

5贺氓、org.apache.ibatis.session.defaults.DefaultSqlSession#selectOne(java.lang.String, java.lang.Object)

6叉瘩、org.apache.ibatis.session.defaults.DefaultSqlSession#selectList(java.lang.String, java.lang.Object)

這里加了一個方法參數(shù)聊品,RowBounds.DEFAULT鹿霸,這是物理分頁傳入的默認(rèn)參數(shù)宽闲,返回的結(jié)果其實(shí)分頁了拉队,但是和沒分頁效果一樣弊知,下面繼續(xù)調(diào)用:

1、String name = mapper.selectNameById(1);

2粱快、org.apache.ibatis.binding.MapperProxy#invoke

3秩彤、org.apache.ibatis.binding.MapperProxy#cachedMapperMethod

4、org.apache.ibatis.binding.MapperMethod#execute

5事哭、org.apache.ibatis.session.defaults.DefaultSqlSession#selectOne(java.lang.String, java.lang.Object)

6漫雷、org.apache.ibatis.session.defaults.DefaultSqlSession#selectList(java.lang.String, java.lang.Object)

7、org.apache.ibatis.session.defaults.DefaultSqlSession#selectList(java.lang.String, java.lang.Object, org.apache.ibatis.session.RowBounds)

我們在執(zhí)行jdbc的時候鳍咱,先編譯SQL語句降盹,獲取一個Statement對象,這里獲取的是一個MappedStatement對象谤辜,這個類對應(yīng)的就是select標(biāo)簽蓄坏。類的屬性和select標(biāo)簽的屬性一致。下面這一行executor.query方法執(zhí)行操作丑念,繼續(xù)看下面的代碼涡戳,使用Executor的對象執(zhí)行,Executor是一個接口渠欺,有兩個實(shí)現(xiàn)類妹蔽,通過工具可以看到這里使用的是CachingExecutor類的對象實(shí)例執(zhí)行的:

1、String name = mapper.selectNameById(1);

2挠将、org.apache.ibatis.binding.MapperProxy#invoke

3胳岂、org.apache.ibatis.binding.MapperProxy#cachedMapperMethod

4、org.apache.ibatis.binding.MapperMethod#execute

5舔稀、org.apache.ibatis.session.defaults.DefaultSqlSession#selectOne(java.lang.String, java.lang.Object)

6乳丰、org.apache.ibatis.session.defaults.DefaultSqlSession#selectList(java.lang.String, java.lang.Object)

7、org.apache.ibatis.session.defaults.DefaultSqlSession#selectList(java.lang.String, java.lang.Object, org.apache.ibatis.session.RowBounds)

8内贮、org.apache.ibatis.executor.CachingExecutor#query(org.apache.ibatis.mapping.MappedStatement, java.lang.Object, org.apache.ibatis.session.RowBounds, org.apache.ibatis.session.ResultHandler)

通過類名我們可以猜測到产园,這個Executor執(zhí)行類是使用內(nèi)存的汞斧,將數(shù)據(jù)保存到緩存中,這樣可以有效的解決增刪改查性能什燕。緩存的作用域?yàn)閙apper(namespace)粘勒,所以同一個namespace的操作會影響到相同作用域下的緩存,這樣不同的域?qū)ν粋€表進(jìn)行操作很有可能導(dǎo)致緩存中的數(shù)據(jù)不一樣屎即,出現(xiàn)問題庙睡,還是不推薦使用。我們看方法的內(nèi)容:

前面兩行是創(chuàng)建緩存值技俐,獲取記錄乘陪,繼續(xù)往下看:

1、String name = mapper.selectNameById(1);

2雕擂、org.apache.ibatis.binding.MapperProxy#invoke

3啡邑、org.apache.ibatis.binding.MapperProxy#cachedMapperMethod

4、org.apache.ibatis.binding.MapperMethod#execute

5井赌、org.apache.ibatis.session.defaults.DefaultSqlSession#selectOne(java.lang.String, java.lang.Object)

6谤逼、org.apache.ibatis.session.defaults.DefaultSqlSession#selectList(java.lang.String, java.lang.Object)

7、org.apache.ibatis.session.defaults.DefaultSqlSession#selectList(java.lang.String, java.lang.Object, org.apache.ibatis.session.RowBounds)

8族展、org.apache.ibatis.executor.CachingExecutor#query(org.apache.ibatis.mapping.MappedStatement, java.lang.Object, org.apache.ibatis.session.RowBounds, org.apache.ibatis.session.ResultHandler)

9森缠、org.apache.ibatis.executor.CachingExecutor#query(org.apache.ibatis.mapping.MappedStatement, java.lang.Object, org.apache.ibatis.session.RowBounds, org.apache.ibatis.session.ResultHandler, org.apache.ibatis.cache.CacheKey, org.apache.ibatis.mapping.BoundSql)

上面這個過程就是一級緩存的內(nèi)容,如果緩存里不為空仪缸,就從緩存中查詢贵涵,如果緩存為空,就查詢數(shù)據(jù)庫恰画,這里啟動程序只進(jìn)行一次查詢宾茂,所以會走查詢數(shù)據(jù)庫的分支,最后一行的delegate對象拴还,也是一個Executor對象跨晴,這里走不使用緩存的分支,執(zhí)行操作使用的BaseExecutor對象:

1片林、String name = mapper.selectNameById(1);

2端盆、org.apache.ibatis.binding.MapperProxy#invoke

3、org.apache.ibatis.binding.MapperProxy#cachedMapperMethod

4费封、org.apache.ibatis.binding.MapperMethod#execute

5焕妙、org.apache.ibatis.session.defaults.DefaultSqlSession#selectOne(java.lang.String, java.lang.Object)

6、org.apache.ibatis.session.defaults.DefaultSqlSession#selectList(java.lang.String, java.lang.Object)

7弓摘、org.apache.ibatis.session.defaults.DefaultSqlSession#selectList(java.lang.String, java.lang.Object, org.apache.ibatis.session.RowBounds)

8焚鹊、org.apache.ibatis.executor.CachingExecutor#query(org.apache.ibatis.mapping.MappedStatement, java.lang.Object, org.apache.ibatis.session.RowBounds, org.apache.ibatis.session.ResultHandler)

9、org.apache.ibatis.executor.CachingExecutor#query(org.apache.ibatis.mapping.MappedStatement, java.lang.Object, org.apache.ibatis.session.RowBounds, org.apache.ibatis.session.ResultHandler, org.apache.ibatis.cache.CacheKey, org.apache.ibatis.mapping.BoundSql)

10韧献、org.apache.ibatis.executor.BaseExecutor#query(org.apache.ibatis.mapping.MappedStatement, java.lang.Object, org.apache.ibatis.session.RowBounds, org.apache.ibatis.session.ResultHandler, org.apache.ibatis.cache.CacheKey, org.apache.ibatis.mapping.BoundSql)

這里從數(shù)據(jù)庫查末患,走的是:

list = queryFromDatabase(ms, parameter, rowBounds, resultHandler, key, boundSql);

這條代碼分支研叫,從名字可以看出從數(shù)據(jù)庫查詢,參數(shù)中傳了很多璧针,除了編譯好的SQL嚷炉,還有分頁,結(jié)果的handler陈莽,等等渤昌,這些是mybatis封裝jdbc后以自己的特色去執(zhí)行SQL的方式虽抄,這種麻煩的方法簡化了我們使用mybatis的方式走搁,下面繼續(xù)看:

1、String name = mapper.selectNameById(1);

2迈窟、org.apache.ibatis.binding.MapperProxy#invoke

3私植、org.apache.ibatis.binding.MapperProxy#cachedMapperMethod

4、org.apache.ibatis.binding.MapperMethod#execute

5车酣、org.apache.ibatis.session.defaults.DefaultSqlSession#selectOne(java.lang.String, java.lang.Object)

6曲稼、org.apache.ibatis.session.defaults.DefaultSqlSession#selectList(java.lang.String, java.lang.Object)

7、org.apache.ibatis.session.defaults.DefaultSqlSession#selectList(java.lang.String, java.lang.Object, org.apache.ibatis.session.RowBounds)

8湖员、org.apache.ibatis.executor.CachingExecutor#query(org.apache.ibatis.mapping.MappedStatement, java.lang.Object, org.apache.ibatis.session.RowBounds, org.apache.ibatis.session.ResultHandler)

9贫悄、org.apache.ibatis.executor.CachingExecutor#query(org.apache.ibatis.mapping.MappedStatement, java.lang.Object, org.apache.ibatis.session.RowBounds, org.apache.ibatis.session.ResultHandler, org.apache.ibatis.cache.CacheKey, org.apache.ibatis.mapping.BoundSql)

10、org.apache.ibatis.executor.BaseExecutor#query(org.apache.ibatis.mapping.MappedStatement, java.lang.Object, org.apache.ibatis.session.RowBounds, org.apache.ibatis.session.ResultHandler, org.apache.ibatis.cache.CacheKey, org.apache.ibatis.mapping.BoundSql)

11娘摔、org.apache.ibatis.executor.BaseExecutor#queryFromDatabase

看代碼:

localCache.putObject(key, EXECUTION_PLACEHOLDER);

這里查詢了一次以后窄坦,加入了一級緩存當(dāng)中,下面就是執(zhí)行doQuery方法:

1凳寺、String name = mapper.selectNameById(1);

2鸭津、org.apache.ibatis.binding.MapperProxy#invoke

3、org.apache.ibatis.binding.MapperProxy#cachedMapperMethod

4肠缨、org.apache.ibatis.binding.MapperMethod#execute

5逆趋、org.apache.ibatis.session.defaults.DefaultSqlSession#selectOne(java.lang.String, java.lang.Object)

6、org.apache.ibatis.session.defaults.DefaultSqlSession#selectList(java.lang.String, java.lang.Object)

7晒奕、org.apache.ibatis.session.defaults.DefaultSqlSession#selectList(java.lang.String, java.lang.Object, org.apache.ibatis.session.RowBounds)

8闻书、org.apache.ibatis.executor.CachingExecutor#query(org.apache.ibatis.mapping.MappedStatement, java.lang.Object, org.apache.ibatis.session.RowBounds, org.apache.ibatis.session.ResultHandler)

9、org.apache.ibatis.executor.CachingExecutor#query(org.apache.ibatis.mapping.MappedStatement, java.lang.Object, org.apache.ibatis.session.RowBounds, org.apache.ibatis.session.ResultHandler, org.apache.ibatis.cache.CacheKey, org.apache.ibatis.mapping.BoundSql)

10脑慧、org.apache.ibatis.executor.BaseExecutor#query(org.apache.ibatis.mapping.MappedStatement, java.lang.Object, org.apache.ibatis.session.RowBounds, org.apache.ibatis.session.ResultHandler, org.apache.ibatis.cache.CacheKey, org.apache.ibatis.mapping.BoundSql)

11魄眉、org.apache.ibatis.executor.BaseExecutor#queryFromDatabase

12、org.apache.ibatis.executor.SimpleExecutor#doQuery

這里進(jìn)入了SimpleExecutor類中漾橙,第一行的Statement stmt =null;代碼有點(diǎn)眼熟杆融,就是我們jdbc中的Statement 對象,說明我們馬上要接近真相了霜运!繼續(xù)脾歇,前面三個是對SQL語句進(jìn)行預(yù)編譯蒋腮,然后執(zhí)行query方法,通過debug藕各,知道下一步執(zhí)行這個方法:

1池摧、String name = mapper.selectNameById(1);

2、org.apache.ibatis.binding.MapperProxy#invoke

3激况、org.apache.ibatis.binding.MapperProxy#cachedMapperMethod

4作彤、org.apache.ibatis.binding.MapperMethod#execute

5、org.apache.ibatis.session.defaults.DefaultSqlSession#selectOne(java.lang.String, java.lang.Object)

6乌逐、org.apache.ibatis.session.defaults.DefaultSqlSession#selectList(java.lang.String, java.lang.Object)

7竭讳、org.apache.ibatis.session.defaults.DefaultSqlSession#selectList(java.lang.String, java.lang.Object, org.apache.ibatis.session.RowBounds)

8、org.apache.ibatis.executor.CachingExecutor#query(org.apache.ibatis.mapping.MappedStatement, java.lang.Object, org.apache.ibatis.session.RowBounds, org.apache.ibatis.session.ResultHandler)

9浙踢、org.apache.ibatis.executor.CachingExecutor#query(org.apache.ibatis.mapping.MappedStatement, java.lang.Object, org.apache.ibatis.session.RowBounds, org.apache.ibatis.session.ResultHandler, org.apache.ibatis.cache.CacheKey, org.apache.ibatis.mapping.BoundSql)

10绢慢、org.apache.ibatis.executor.BaseExecutor#query(org.apache.ibatis.mapping.MappedStatement, java.lang.Object, org.apache.ibatis.session.RowBounds, org.apache.ibatis.session.ResultHandler, org.apache.ibatis.cache.CacheKey, org.apache.ibatis.mapping.BoundSql)

11、org.apache.ibatis.executor.BaseExecutor#queryFromDatabase

12洛波、org.apache.ibatis.executor.SimpleExecutor#doQuery

13胰舆、org.apache.ibatis.executor.statement.RoutingStatementHandler#query

這里就是一行調(diào)用,繼續(xù)debug:

1蹬挤、String name = mapper.selectNameById(1);

2缚窿、org.apache.ibatis.binding.MapperProxy#invoke

3、org.apache.ibatis.binding.MapperProxy#cachedMapperMethod

4焰扳、org.apache.ibatis.binding.MapperMethod#execute

5倦零、org.apache.ibatis.session.defaults.DefaultSqlSession#selectOne(java.lang.String, java.lang.Object)

6、org.apache.ibatis.session.defaults.DefaultSqlSession#selectList(java.lang.String, java.lang.Object)

7蓝翰、org.apache.ibatis.session.defaults.DefaultSqlSession#selectList(java.lang.String, java.lang.Object, org.apache.ibatis.session.RowBounds)

8光绕、org.apache.ibatis.executor.CachingExecutor#query(org.apache.ibatis.mapping.MappedStatement, java.lang.Object, org.apache.ibatis.session.RowBounds, org.apache.ibatis.session.ResultHandler)

9、org.apache.ibatis.executor.CachingExecutor#query(org.apache.ibatis.mapping.MappedStatement, java.lang.Object, org.apache.ibatis.session.RowBounds, org.apache.ibatis.session.ResultHandler, org.apache.ibatis.cache.CacheKey, org.apache.ibatis.mapping.BoundSql)

10畜份、org.apache.ibatis.executor.BaseExecutor#query(org.apache.ibatis.mapping.MappedStatement, java.lang.Object, org.apache.ibatis.session.RowBounds, org.apache.ibatis.session.ResultHandler, org.apache.ibatis.cache.CacheKey, org.apache.ibatis.mapping.BoundSql)

11诞帐、org.apache.ibatis.executor.BaseExecutor#queryFromDatabase

12、org.apache.ibatis.executor.SimpleExecutor#doQuery

13爆雹、org.apache.ibatis.executor.statement.RoutingStatementHandler#query

14停蕉、org.apache.ibatis.executor.statement.PreparedStatementHandler#query

第一行是jdk中jdbc的類,執(zhí)行獲取預(yù)編譯操作钙态,然后執(zhí)行了ps.execute();慧起,這個就是我們的jdbc方法!終于到這里了册倒!resultSetHandler是mybatis的對象蚓挤,包裝jdbc的結(jié)果,我們繼續(xù)看:

1、String name = mapper.selectNameById(1);

2灿意、org.apache.ibatis.binding.MapperProxy#invoke

3估灿、org.apache.ibatis.binding.MapperProxy#cachedMapperMethod

4、org.apache.ibatis.binding.MapperMethod#execute

5缤剧、org.apache.ibatis.session.defaults.DefaultSqlSession#selectOne(java.lang.String, java.lang.Object)

6馅袁、org.apache.ibatis.session.defaults.DefaultSqlSession#selectList(java.lang.String, java.lang.Object)

7、org.apache.ibatis.session.defaults.DefaultSqlSession#selectList(java.lang.String, java.lang.Object, org.apache.ibatis.session.RowBounds)

8荒辕、org.apache.ibatis.executor.CachingExecutor#query(org.apache.ibatis.mapping.MappedStatement, java.lang.Object, org.apache.ibatis.session.RowBounds, org.apache.ibatis.session.ResultHandler)

9汗销、org.apache.ibatis.executor.CachingExecutor#query(org.apache.ibatis.mapping.MappedStatement, java.lang.Object, org.apache.ibatis.session.RowBounds, org.apache.ibatis.session.ResultHandler, org.apache.ibatis.cache.CacheKey, org.apache.ibatis.mapping.BoundSql)

10、org.apache.ibatis.executor.BaseExecutor#query(org.apache.ibatis.mapping.MappedStatement, java.lang.Object, org.apache.ibatis.session.RowBounds, org.apache.ibatis.session.ResultHandler, org.apache.ibatis.cache.CacheKey, org.apache.ibatis.mapping.BoundSql)

11抵窒、org.apache.ibatis.executor.BaseExecutor#queryFromDatabase

12弛针、org.apache.ibatis.executor.SimpleExecutor#doQuery

13、org.apache.ibatis.executor.statement.RoutingStatementHandler#query

14估脆、org.apache.ibatis.executor.statement.PreparedStatementHandler#query

15钦奋、org.apache.ibatis.executor.resultset.DefaultResultSetHandler#handleResultSets

ResultSetHandler負(fù)責(zé)處理兩件事,一是處理Statement執(zhí)行后產(chǎn)生的結(jié)果集疙赠,生成結(jié)果列表,二是處理存儲過程執(zhí)行后的輸出參數(shù)朦拖。DefaultResultSetHandler類是ResultSetHandler的默認(rèn)實(shí)現(xiàn)圃阳,這里執(zhí)行了這個類的handleResultSets方法,其實(shí)現(xiàn)的步驟就是將Statement執(zhí)行后的結(jié)果集璧帝,按照Mapper文件中配置的ResultType或ResultMap來封裝成對應(yīng)的對象捍岳,最后將封裝的對象返回即可,這里有一行代碼:

ResultSetWrapper rsw = getFirstResultSet(stmt);

我們進(jìn)入getFirstResultSet方法看一看:

這里的代碼很眼熟了睬隶,就是jdbc接收結(jié)果的過程锣夹,最后一行把這個結(jié)果封裝成了mybatis中的結(jié)果對象,封裝的過程如下:

這里面包含的記過的很多熟悉苏潜,類型银萍,名稱,對象的類型恤左,等等贴唇。我們繼續(xù)來看handleResultSets方法,組合好多個返回結(jié)果的list后飞袋,我們看最后一行代碼戳气,執(zhí)行collapseSingleResultList方法:

1、String name = mapper.selectNameById(1);

2巧鸭、org.apache.ibatis.binding.MapperProxy#invoke

3瓶您、org.apache.ibatis.binding.MapperProxy#cachedMapperMethod

4、org.apache.ibatis.binding.MapperMethod#execute

5、org.apache.ibatis.session.defaults.DefaultSqlSession#selectOne(java.lang.String, java.lang.Object)

6呀袱、org.apache.ibatis.session.defaults.DefaultSqlSession#selectList(java.lang.String, java.lang.Object)

7芯肤、org.apache.ibatis.session.defaults.DefaultSqlSession#selectList(java.lang.String, java.lang.Object, org.apache.ibatis.session.RowBounds)

8、org.apache.ibatis.executor.CachingExecutor#query(org.apache.ibatis.mapping.MappedStatement, java.lang.Object, org.apache.ibatis.session.RowBounds, org.apache.ibatis.session.ResultHandler)

9压鉴、org.apache.ibatis.executor.CachingExecutor#query(org.apache.ibatis.mapping.MappedStatement, java.lang.Object, org.apache.ibatis.session.RowBounds, org.apache.ibatis.session.ResultHandler, org.apache.ibatis.cache.CacheKey, org.apache.ibatis.mapping.BoundSql)

10崖咨、org.apache.ibatis.executor.BaseExecutor#query(org.apache.ibatis.mapping.MappedStatement, java.lang.Object, org.apache.ibatis.session.RowBounds, org.apache.ibatis.session.ResultHandler, org.apache.ibatis.cache.CacheKey, org.apache.ibatis.mapping.BoundSql)

11、org.apache.ibatis.executor.BaseExecutor#queryFromDatabase

12油吭、org.apache.ibatis.executor.SimpleExecutor#doQuery

13击蹲、org.apache.ibatis.executor.statement.RoutingStatementHandler#query

14、org.apache.ibatis.executor.statement.PreparedStatementHandler#query

15婉宰、org.apache.ibatis.executor.resultset.DefaultResultSetHandler#handleResultSets

16歌豺、org.apache.ibatis.executor.resultset.DefaultResultSetHandler#collapseSingleResultList

從判斷可以看出,在判斷是不是只有一條結(jié)果心包,這樣封裝返回結(jié)果的對象就執(zhí)行完了类咧。我們再次返回前面的方法:

1、String name = mapper.selectNameById(1);

2蟹腾、org.apache.ibatis.binding.MapperProxy#invoke

3痕惋、org.apache.ibatis.binding.MapperProxy#cachedMapperMethod

4、org.apache.ibatis.binding.MapperMethod#execute

5娃殖、org.apache.ibatis.session.defaults.DefaultSqlSession#selectOne(java.lang.String, java.lang.Object)

6值戳、org.apache.ibatis.session.defaults.DefaultSqlSession#selectList(java.lang.String, java.lang.Object)

7、org.apache.ibatis.session.defaults.DefaultSqlSession#selectList(java.lang.String, java.lang.Object, org.apache.ibatis.session.RowBounds)

8炉爆、org.apache.ibatis.executor.CachingExecutor#query(org.apache.ibatis.mapping.MappedStatement, java.lang.Object, org.apache.ibatis.session.RowBounds, org.apache.ibatis.session.ResultHandler)

9堕虹、org.apache.ibatis.executor.CachingExecutor#query(org.apache.ibatis.mapping.MappedStatement, java.lang.Object, org.apache.ibatis.session.RowBounds, org.apache.ibatis.session.ResultHandler, org.apache.ibatis.cache.CacheKey, org.apache.ibatis.mapping.BoundSql)

10、org.apache.ibatis.executor.BaseExecutor#query(org.apache.ibatis.mapping.MappedStatement, java.lang.Object, org.apache.ibatis.session.RowBounds, org.apache.ibatis.session.ResultHandler, org.apache.ibatis.cache.CacheKey, org.apache.ibatis.mapping.BoundSql)

11芬首、org.apache.ibatis.executor.BaseExecutor#queryFromDatabase

12赴捞、org.apache.ibatis.executor.SimpleExecutor#doQuery

13、org.apache.ibatis.executor.statement.RoutingStatementHandler#query

14郁稍、org.apache.ibatis.executor.statement.PreparedStatementHandler#query

15赦政、org.apache.ibatis.executor.resultset.DefaultResultSetHandler#handleResultSets

16、org.apache.ibatis.executor.resultset.DefaultResultSetHandler#collapseSingleResultList

17艺晴、org.apache.ibatis.executor.statement.PreparedStatementHandler#query

這里是前面的方法昼钻,返回的就是符合類型的結(jié)果的list,無論一條還是多條封寞,繼續(xù)debug:

1然评、String name = mapper.selectNameById(1);

2、org.apache.ibatis.binding.MapperProxy#invoke

3狈究、org.apache.ibatis.binding.MapperProxy#cachedMapperMethod

4碗淌、org.apache.ibatis.binding.MapperMethod#execute

5、org.apache.ibatis.session.defaults.DefaultSqlSession#selectOne(java.lang.String, java.lang.Object)

6、org.apache.ibatis.session.defaults.DefaultSqlSession#selectList(java.lang.String, java.lang.Object)

7亿眠、org.apache.ibatis.session.defaults.DefaultSqlSession#selectList(java.lang.String, java.lang.Object, org.apache.ibatis.session.RowBounds)

8碎罚、org.apache.ibatis.executor.CachingExecutor#query(org.apache.ibatis.mapping.MappedStatement, java.lang.Object, org.apache.ibatis.session.RowBounds, org.apache.ibatis.session.ResultHandler)

9、org.apache.ibatis.executor.CachingExecutor#query(org.apache.ibatis.mapping.MappedStatement, java.lang.Object, org.apache.ibatis.session.RowBounds, org.apache.ibatis.session.ResultHandler, org.apache.ibatis.cache.CacheKey, org.apache.ibatis.mapping.BoundSql)

10纳像、org.apache.ibatis.executor.BaseExecutor#query(org.apache.ibatis.mapping.MappedStatement, java.lang.Object, org.apache.ibatis.session.RowBounds, org.apache.ibatis.session.ResultHandler, org.apache.ibatis.cache.CacheKey, org.apache.ibatis.mapping.BoundSql)

11荆烈、org.apache.ibatis.executor.BaseExecutor#queryFromDatabase

12、org.apache.ibatis.executor.SimpleExecutor#doQuery

13竟趾、org.apache.ibatis.executor.statement.RoutingStatementHandler#query

14憔购、org.apache.ibatis.executor.statement.PreparedStatementHandler#query

15、org.apache.ibatis.executor.resultset.DefaultResultSetHandler#handleResultSets

16岔帽、org.apache.ibatis.executor.resultset.DefaultResultSetHandler#collapseSingleResultList

17玫鸟、org.apache.ibatis.executor.statement.PreparedStatementHandler#query

18、org.apache.ibatis.executor.statement.RoutingStatementHandler#query

繼續(xù)往回執(zhí)行:

1犀勒、String name = mapper.selectNameById(1);

2屎飘、org.apache.ibatis.binding.MapperProxy#invoke

3、org.apache.ibatis.binding.MapperProxy#cachedMapperMethod

4贾费、org.apache.ibatis.binding.MapperMethod#execute

5钦购、org.apache.ibatis.session.defaults.DefaultSqlSession#selectOne(java.lang.String, java.lang.Object)

6、org.apache.ibatis.session.defaults.DefaultSqlSession#selectList(java.lang.String, java.lang.Object)

7铸本、org.apache.ibatis.session.defaults.DefaultSqlSession#selectList(java.lang.String, java.lang.Object, org.apache.ibatis.session.RowBounds)

8肮雨、org.apache.ibatis.executor.CachingExecutor#query(org.apache.ibatis.mapping.MappedStatement, java.lang.Object, org.apache.ibatis.session.RowBounds, org.apache.ibatis.session.ResultHandler)

9、org.apache.ibatis.executor.CachingExecutor#query(org.apache.ibatis.mapping.MappedStatement, java.lang.Object, org.apache.ibatis.session.RowBounds, org.apache.ibatis.session.ResultHandler, org.apache.ibatis.cache.CacheKey, org.apache.ibatis.mapping.BoundSql)

10箱玷、org.apache.ibatis.executor.BaseExecutor#query(org.apache.ibatis.mapping.MappedStatement, java.lang.Object, org.apache.ibatis.session.RowBounds, org.apache.ibatis.session.ResultHandler, org.apache.ibatis.cache.CacheKey, org.apache.ibatis.mapping.BoundSql)

11、org.apache.ibatis.executor.BaseExecutor#queryFromDatabase

12陌宿、org.apache.ibatis.executor.SimpleExecutor#doQuery

13锡足、org.apache.ibatis.executor.statement.RoutingStatementHandler#query

14、org.apache.ibatis.executor.statement.PreparedStatementHandler#query

15壳坪、org.apache.ibatis.executor.resultset.DefaultResultSetHandler#handleResultSets

16舶得、org.apache.ibatis.executor.resultset.DefaultResultSetHandler#collapseSingleResultList

17、org.apache.ibatis.executor.statement.PreparedStatementHandler#query

18爽蝴、org.apache.ibatis.executor.statement.RoutingStatementHandler#query

19沐批、org.apache.ibatis.executor.SimpleExecutor#doQuery

繼續(xù)往回執(zhí)行:

1、String name = mapper.selectNameById(1);

2蝎亚、org.apache.ibatis.binding.MapperProxy#invoke

3九孩、org.apache.ibatis.binding.MapperProxy#cachedMapperMethod

4、org.apache.ibatis.binding.MapperMethod#execute

5发框、org.apache.ibatis.session.defaults.DefaultSqlSession#selectOne(java.lang.String, java.lang.Object)

6躺彬、org.apache.ibatis.session.defaults.DefaultSqlSession#selectList(java.lang.String, java.lang.Object)

7、org.apache.ibatis.session.defaults.DefaultSqlSession#selectList(java.lang.String, java.lang.Object, org.apache.ibatis.session.RowBounds)

8、org.apache.ibatis.executor.CachingExecutor#query(org.apache.ibatis.mapping.MappedStatement, java.lang.Object, org.apache.ibatis.session.RowBounds, org.apache.ibatis.session.ResultHandler)

9宪拥、org.apache.ibatis.executor.CachingExecutor#query(org.apache.ibatis.mapping.MappedStatement, java.lang.Object, org.apache.ibatis.session.RowBounds, org.apache.ibatis.session.ResultHandler, org.apache.ibatis.cache.CacheKey, org.apache.ibatis.mapping.BoundSql)

10仿野、org.apache.ibatis.executor.BaseExecutor#query(org.apache.ibatis.mapping.MappedStatement, java.lang.Object, org.apache.ibatis.session.RowBounds, org.apache.ibatis.session.ResultHandler, org.apache.ibatis.cache.CacheKey, org.apache.ibatis.mapping.BoundSql)

11、org.apache.ibatis.executor.BaseExecutor#queryFromDatabase

12她君、org.apache.ibatis.executor.SimpleExecutor#doQuery

13脚作、org.apache.ibatis.executor.statement.RoutingStatementHandler#query

14、org.apache.ibatis.executor.statement.PreparedStatementHandler#query

15缔刹、org.apache.ibatis.executor.resultset.DefaultResultSetHandler#handleResultSets

16球涛、org.apache.ibatis.executor.resultset.DefaultResultSetHandler#collapseSingleResultList

17、org.apache.ibatis.executor.statement.PreparedStatementHandler#query

18桨螺、org.apache.ibatis.executor.statement.RoutingStatementHandler#query

19宾符、org.apache.ibatis.executor.SimpleExecutor#doQuery

20、org.apache.ibatis.executor.BaseExecutor#queryFromDatabase

這里把最終的查詢結(jié)果放到了一級緩存中灭翔,然后繼續(xù)往回執(zhí)行:

1魏烫、String name = mapper.selectNameById(1);

2、org.apache.ibatis.binding.MapperProxy#invoke

3肝箱、org.apache.ibatis.binding.MapperProxy#cachedMapperMethod

4哄褒、org.apache.ibatis.binding.MapperMethod#execute

5、org.apache.ibatis.session.defaults.DefaultSqlSession#selectOne(java.lang.String, java.lang.Object)

6煌张、org.apache.ibatis.session.defaults.DefaultSqlSession#selectList(java.lang.String, java.lang.Object)

7呐赡、org.apache.ibatis.session.defaults.DefaultSqlSession#selectList(java.lang.String, java.lang.Object, org.apache.ibatis.session.RowBounds)

8、org.apache.ibatis.executor.CachingExecutor#query(org.apache.ibatis.mapping.MappedStatement, java.lang.Object, org.apache.ibatis.session.RowBounds, org.apache.ibatis.session.ResultHandler)

9骏融、org.apache.ibatis.executor.CachingExecutor#query(org.apache.ibatis.mapping.MappedStatement, java.lang.Object, org.apache.ibatis.session.RowBounds, org.apache.ibatis.session.ResultHandler, org.apache.ibatis.cache.CacheKey, org.apache.ibatis.mapping.BoundSql)

10链嘀、org.apache.ibatis.executor.BaseExecutor#query(org.apache.ibatis.mapping.MappedStatement, java.lang.Object, org.apache.ibatis.session.RowBounds, org.apache.ibatis.session.ResultHandler, org.apache.ibatis.cache.CacheKey, org.apache.ibatis.mapping.BoundSql)

11、org.apache.ibatis.executor.BaseExecutor#queryFromDatabase

12档玻、org.apache.ibatis.executor.SimpleExecutor#doQuery

13怀泊、org.apache.ibatis.executor.statement.RoutingStatementHandler#query

14、org.apache.ibatis.executor.statement.PreparedStatementHandler#query

15误趴、org.apache.ibatis.executor.resultset.DefaultResultSetHandler#handleResultSets

16霹琼、org.apache.ibatis.executor.resultset.DefaultResultSetHandler#collapseSingleResultList

17、org.apache.ibatis.executor.statement.PreparedStatementHandler#query

18凉当、org.apache.ibatis.executor.statement.RoutingStatementHandler#query

19枣申、org.apache.ibatis.executor.SimpleExecutor#doQuery

20、org.apache.ibatis.executor.BaseExecutor#queryFromDatabase

21看杭、org.apache.ibatis.executor.BaseExecutor#query(org.apache.ibatis.mapping.MappedStatement, java.lang.Object, org.apache.ibatis.session.RowBounds, org.apache.ibatis.session.ResultHandler, org.apache.ibatis.cache.CacheKey, org.apache.ibatis.mapping.BoundSql)

這里面對緩存最后進(jìn)行處理忠藤,繼續(xù)往回看:

1、String name = mapper.selectNameById(1);

2泊窘、org.apache.ibatis.binding.MapperProxy#invoke

3熄驼、org.apache.ibatis.binding.MapperProxy#cachedMapperMethod

4像寒、org.apache.ibatis.binding.MapperMethod#execute

5、org.apache.ibatis.session.defaults.DefaultSqlSession#selectOne(java.lang.String, java.lang.Object)

6瓜贾、org.apache.ibatis.session.defaults.DefaultSqlSession#selectList(java.lang.String, java.lang.Object)

7诺祸、org.apache.ibatis.session.defaults.DefaultSqlSession#selectList(java.lang.String, java.lang.Object, org.apache.ibatis.session.RowBounds)

8、org.apache.ibatis.executor.CachingExecutor#query(org.apache.ibatis.mapping.MappedStatement, java.lang.Object, org.apache.ibatis.session.RowBounds, org.apache.ibatis.session.ResultHandler)

9祭芦、org.apache.ibatis.executor.CachingExecutor#query(org.apache.ibatis.mapping.MappedStatement, java.lang.Object, org.apache.ibatis.session.RowBounds, org.apache.ibatis.session.ResultHandler, org.apache.ibatis.cache.CacheKey, org.apache.ibatis.mapping.BoundSql)

10筷笨、org.apache.ibatis.executor.BaseExecutor#query(org.apache.ibatis.mapping.MappedStatement, java.lang.Object, org.apache.ibatis.session.RowBounds, org.apache.ibatis.session.ResultHandler, org.apache.ibatis.cache.CacheKey, org.apache.ibatis.mapping.BoundSql)

11、org.apache.ibatis.executor.BaseExecutor#queryFromDatabase

12龟劲、org.apache.ibatis.executor.SimpleExecutor#doQuery

13胃夏、org.apache.ibatis.executor.statement.RoutingStatementHandler#query

14、org.apache.ibatis.executor.statement.PreparedStatementHandler#query

15昌跌、org.apache.ibatis.executor.resultset.DefaultResultSetHandler#handleResultSets

16仰禀、org.apache.ibatis.executor.resultset.DefaultResultSetHandler#collapseSingleResultList

17、org.apache.ibatis.executor.statement.PreparedStatementHandler#query

18蚕愤、org.apache.ibatis.executor.statement.RoutingStatementHandler#query

19答恶、org.apache.ibatis.executor.SimpleExecutor#doQuery

20、org.apache.ibatis.executor.BaseExecutor#queryFromDatabase

21萍诱、org.apache.ibatis.executor.BaseExecutor#query(org.apache.ibatis.mapping.MappedStatement, java.lang.Object, org.apache.ibatis.session.RowBounds, org.apache.ibatis.session.ResultHandler, org.apache.ibatis.cache.CacheKey, org.apache.ibatis.mapping.BoundSql)

22悬嗓、org.apache.ibatis.executor.CachingExecutor#query(org.apache.ibatis.mapping.MappedStatement, java.lang.Object, org.apache.ibatis.session.RowBounds, org.apache.ibatis.session.ResultHandler, org.apache.ibatis.cache.CacheKey, org.apache.ibatis.mapping.BoundSql)

23、org.apache.ibatis.executor.CachingExecutor#query(org.apache.ibatis.mapping.MappedStatement, java.lang.Object, org.apache.ibatis.session.RowBounds, org.apache.ibatis.session.ResultHandler)

24裕坊、org.apache.ibatis.session.defaults.DefaultSqlSession#selectList(java.lang.String, java.lang.Object, org.apache.ibatis.session.RowBounds)

25包竹、org.apache.ibatis.session.defaults.DefaultSqlSession#selectList(java.lang.String, java.lang.Object)

26、org.apache.ibatis.session.defaults.DefaultSqlSession#selectOne(java.lang.String, java.lang.Object)

最后帶著list回到了selectOne這里籍凝,

查詢成功以后周瞎,返回了第一個對象,下面是代理對象:

1饵蒂、String name = mapper.selectNameById(1);

2堰氓、org.apache.ibatis.binding.MapperProxy#invoke

3、org.apache.ibatis.binding.MapperProxy#cachedMapperMethod

4苹享、org.apache.ibatis.binding.MapperMethod#execute

5、org.apache.ibatis.session.defaults.DefaultSqlSession#selectOne(java.lang.String, java.lang.Object)

6浴麻、org.apache.ibatis.session.defaults.DefaultSqlSession#selectList(java.lang.String, java.lang.Object)

7得问、org.apache.ibatis.session.defaults.DefaultSqlSession#selectList(java.lang.String, java.lang.Object, org.apache.ibatis.session.RowBounds)

8敦跌、org.apache.ibatis.executor.CachingExecutor#query(org.apache.ibatis.mapping.MappedStatement, java.lang.Object, org.apache.ibatis.session.RowBounds, org.apache.ibatis.session.ResultHandler)

9旧乞、org.apache.ibatis.executor.CachingExecutor#query(org.apache.ibatis.mapping.MappedStatement, java.lang.Object, org.apache.ibatis.session.RowBounds, org.apache.ibatis.session.ResultHandler, org.apache.ibatis.cache.CacheKey, org.apache.ibatis.mapping.BoundSql)

10、org.apache.ibatis.executor.BaseExecutor#query(org.apache.ibatis.mapping.MappedStatement, java.lang.Object, org.apache.ibatis.session.RowBounds, org.apache.ibatis.session.ResultHandler, org.apache.ibatis.cache.CacheKey, org.apache.ibatis.mapping.BoundSql)

11万俗、org.apache.ibatis.executor.BaseExecutor#queryFromDatabase

12膏萧、org.apache.ibatis.executor.SimpleExecutor#doQuery

13漓骚、org.apache.ibatis.executor.statement.RoutingStatementHandler#query

14蝌衔、org.apache.ibatis.executor.statement.PreparedStatementHandler#query

15、org.apache.ibatis.executor.resultset.DefaultResultSetHandler#handleResultSets

16蝌蹂、org.apache.ibatis.executor.resultset.DefaultResultSetHandler#collapseSingleResultList

17噩斟、org.apache.ibatis.executor.statement.PreparedStatementHandler#query

18、org.apache.ibatis.executor.statement.RoutingStatementHandler#query

19孤个、org.apache.ibatis.executor.SimpleExecutor#doQuery

20剃允、org.apache.ibatis.executor.BaseExecutor#queryFromDatabase

21、org.apache.ibatis.executor.BaseExecutor#query(org.apache.ibatis.mapping.MappedStatement, java.lang.Object, org.apache.ibatis.session.RowBounds, org.apache.ibatis.session.ResultHandler, org.apache.ibatis.cache.CacheKey, org.apache.ibatis.mapping.BoundSql)

22齐鲤、org.apache.ibatis.executor.CachingExecutor#query(org.apache.ibatis.mapping.MappedStatement, java.lang.Object, org.apache.ibatis.session.RowBounds, org.apache.ibatis.session.ResultHandler, org.apache.ibatis.cache.CacheKey, org.apache.ibatis.mapping.BoundSql)

23斥废、org.apache.ibatis.executor.CachingExecutor#query(org.apache.ibatis.mapping.MappedStatement, java.lang.Object, org.apache.ibatis.session.RowBounds, org.apache.ibatis.session.ResultHandler)?

24、org.apache.ibatis.session.defaults.DefaultSqlSession#selectList(java.lang.String, java.lang.Object, org.apache.ibatis.session.RowBounds)

25给郊、org.apache.ibatis.session.defaults.DefaultSqlSession#selectList(java.lang.String, java.lang.Object)

26牡肉、org.apache.ibatis.session.defaults.DefaultSqlSession#selectOne(java.lang.String, java.lang.Object)

27、org.apache.ibatis.binding.MapperMethod#execute

28淆九、org.apache.ibatis.binding.MapperProxy#invoke

29统锤、String name = mapper.selectNameById(1);

最終我們回到了調(diào)用的地方,返回了查詢的name吩屹!




總結(jié)

來總結(jié)一下跪另,通過debug看源碼是一個不太會看源碼的人的一個不錯的方法,我們上面通過debug來查看了mybatis查詢的整個過程煤搜,中間的一級緩存免绿,涉及到的幾種查詢Executor,獲取返回結(jié)果的ResultSetHandler擦盾,編譯的StatementHandler嘲驾,物理分頁的RowBounds等等幾個對象是如果對jdbc查詢的整個過程進(jìn)行潤色的,查詢的整個過程在這個源碼分析中是最復(fù)雜的迹卢,正是由于這個復(fù)雜辽故,我們才能輕松的使用mybatis!

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
  • 序言:七十年代末腐碱,一起剝皮案震驚了整個濱河市誊垢,隨后出現(xiàn)的幾起案子,更是在濱河造成了極大的恐慌症见,老刑警劉巖喂走,帶你破解...
    沈念sama閱讀 222,729評論 6 517
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件,死亡現(xiàn)場離奇詭異谋作,居然都是意外死亡芋肠,警方通過查閱死者的電腦和手機(jī),發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 95,226評論 3 399
  • 文/潘曉璐 我一進(jìn)店門遵蚜,熙熙樓的掌柜王于貴愁眉苦臉地迎上來帖池,“玉大人奈惑,你說我怎么就攤上這事∷冢” “怎么了肴甸?”我有些...
    開封第一講書人閱讀 169,461評論 0 362
  • 文/不壞的土叔 我叫張陵,是天一觀的道長帮孔。 經(jīng)常有香客問我雷滋,道長,這世上最難降的妖魔是什么文兢? 我笑而不...
    開封第一講書人閱讀 60,135評論 1 300
  • 正文 為了忘掉前任晤斩,我火速辦了婚禮,結(jié)果婚禮上姆坚,老公的妹妹穿的比我還像新娘澳泵。我一直安慰自己,他們只是感情好兼呵,可當(dāng)我...
    茶點(diǎn)故事閱讀 69,130評論 6 398
  • 文/花漫 我一把揭開白布兔辅。 她就那樣靜靜地躺著,像睡著了一般击喂。 火紅的嫁衣襯著肌膚如雪维苔。 梳的紋絲不亂的頭發(fā)上,一...
    開封第一講書人閱讀 52,736評論 1 312
  • 那天懂昂,我揣著相機(jī)與錄音介时,去河邊找鬼。 笑死凌彬,一個胖子當(dāng)著我的面吹牛沸柔,可吹牛的內(nèi)容都是我干的。 我是一名探鬼主播铲敛,決...
    沈念sama閱讀 41,179評論 3 422
  • 文/蒼蘭香墨 我猛地睜開眼褐澎,長吁一口氣:“原來是場噩夢啊……” “哼!你這毒婦竟也來了伐蒋?” 一聲冷哼從身側(cè)響起工三,我...
    開封第一講書人閱讀 40,124評論 0 277
  • 序言:老撾萬榮一對情侶失蹤,失蹤者是張志新(化名)和其女友劉穎先鱼,沒想到半個月后徒蟆,有當(dāng)?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體,經(jīng)...
    沈念sama閱讀 46,657評論 1 320
  • 正文 獨(dú)居荒郊野嶺守林人離奇死亡型型,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點(diǎn)故事閱讀 38,723評論 3 342
  • 正文 我和宋清朗相戀三年,在試婚紗的時候發(fā)現(xiàn)自己被綠了全蝶。 大學(xué)時的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片闹蒜。...
    茶點(diǎn)故事閱讀 40,872評論 1 353
  • 序言:一個原本活蹦亂跳的男人離奇死亡寺枉,死狀恐怖,靈堂內(nèi)的尸體忽然破棺而出绷落,到底是詐尸還是另有隱情姥闪,我是刑警寧澤,帶...
    沈念sama閱讀 36,533評論 5 351
  • 正文 年R本政府宣布砌烁,位于F島的核電站筐喳,受9級特大地震影響,放射性物質(zhì)發(fā)生泄漏函喉。R本人自食惡果不足惜避归,卻給世界環(huán)境...
    茶點(diǎn)故事閱讀 42,213評論 3 336
  • 文/蒙蒙 一、第九天 我趴在偏房一處隱蔽的房頂上張望管呵。 院中可真熱鬧梳毙,春花似錦、人聲如沸捐下。這莊子的主人今日做“春日...
    開封第一講書人閱讀 32,700評論 0 25
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽坷襟。三九已至奸柬,卻和暖如春,著一層夾襖步出監(jiān)牢的瞬間婴程,已是汗流浹背廓奕。 一陣腳步聲響...
    開封第一講書人閱讀 33,819評論 1 274
  • 我被黑心中介騙來泰國打工, 沒想到剛下飛機(jī)就差點(diǎn)兒被人妖公主榨干…… 1. 我叫王不留排抬,地道東北人懂从。 一個月前我還...
    沈念sama閱讀 49,304評論 3 379
  • 正文 我出身青樓,卻偏偏與公主長得像蹲蒲,于是被迫代替她去往敵國和親番甩。 傳聞我的和親對象是個殘疾皇子,可洞房花燭夜當(dāng)晚...
    茶點(diǎn)故事閱讀 45,876評論 2 361