亚洲激情专区-91九色丨porny丨老师-久久久久久久女国产乱让韩-国产精品午夜小视频观看

溫馨提示×

溫馨提示×

您好,登錄后才能下訂單哦!

密碼登錄×
登錄注冊×
其他方式登錄
點擊 登錄注冊 即表示同意《億速云用戶服務條款》

Mybatis第三方PageHelper分頁插件怎么用

發布時間:2022-02-23 14:09:04 來源:億速云 閱讀:267 作者:小新 欄目:開發技術

這篇文章將為大家詳細講解有關Mybatis第三方PageHelper分頁插件怎么用,小編覺得挺實用的,因此分享給大家做個參考,希望大家閱讀完這篇文章后可以有所收獲。

    用法

    Mybatis第三方PageHelper分頁插件怎么用Mybatis第三方PageHelper分頁插件怎么用

    此時commentAnalyses為Page對象(PageHelper插件包內定義的)

    Mybatis第三方PageHelper分頁插件怎么用

    而Page對象繼承自JDK中的ArrayList,擴展并封裝了一些page相關的字段,如頁碼,每頁大小,總記錄數,總頁數等。

    Mybatis第三方PageHelper分頁插件怎么用

    Mybatis第三方PageHelper分頁插件怎么用原理

    我們就加了一行,它是如何幫助我們實現分頁的呢?請往下看。

    PageHelper.startPage做了什么

    我們看這一行PageHelper.startPage(pageIndex, pageSize);做了什么。這個類中重載了好多個startPage方法,最終調用到如下的一個方法

    Mybatis第三方PageHelper分頁插件怎么用

    Mybatis第三方PageHelper分頁插件怎么用可以看到該方法將分頁信息作為構造器參數實例化Page對象,調用SqlUtil.getLocalPage()獲取一個舊的Page對象,最后調用SqlUtil.setLocalPage(page);把新創建的Page對象set進去。

    我們看看這兩個方法做了什么。如下,很簡單,從ThreadLocal中獲取Page對象,將Page對象set到ThreadLocal中。知道ThreadLocal作用的不用多說,不知道的可以理解為用于保存本地變量,并與線程綁定。

    Mybatis第三方PageHelper分頁插件怎么用

    Mybatis第三方PageHelper分頁插件怎么用看到這我們暫且將這一行的作用記為,創建并保存Page對象(分頁信息)到ThreadLocal中。

    Page分頁信息在哪使用

    那么既然保存了,就有使用的地方。

    我通過代碼追蹤的方式定位到被調用的地方,通過回溯,發現是從這個類com.github.pagehelper.dialect.AbstractDialect發起調用的

    Mybatis第三方PageHelper分頁插件怎么用

    點進去看了一下,主要是取出Page對象用于做一些判斷,或保存page相關的信息。應該后續會涉及到

    Mybatis第三方PageHelper分頁插件怎么用

    攔截器

    上述AbstractDialect類中的這些方法再回溯,指向了

    com.github.pagehelper.util.SqlUtil#doIntercept方法,intercep調用了doIntercep方法,

    Mybatis第三方PageHelper分頁插件怎么用

    繼續往上追蹤來到了com.github.pagehelper.PageHelper#intercept,這是Interceptor接口的方法。

    Mybatis第三方PageHelper分頁插件怎么用

    然后是org.apache.ibatis.plugin.Plugin#invoke調用了com.github.pagehelper.PageHelper#intercept

    可以看到PageHelper實現了Interceptor,這個接口是Mybatis官方提供的,中文意思是攔截器,所以有可能是通過實現這個攔截器做了某些操作來實現分頁的。

    插件

    通過代碼追蹤我們看到Interceptor的intercept方法是在Mybatis的一個org.apache.ibatis.plugin.Plugin類的invoke方法中調用的,而這個Plugin類實現了JDK的java.lang.reflect.InvocationHandler接口,這是JDK代理接口。

    Mybatis第三方PageHelper分頁插件怎么用

    這個Plugin中有一個wrap方法會返回一個代理類,所以當調用這個代理類的方法時就會走到上面的invoke方法,就可能會進到攔截器的intercept方法。

    Mybatis第三方PageHelper分頁插件怎么用

    所以我們看這個warp在哪調的,就知道啥時候創建這個代理類。就是在上面的PageHelper中,再貼一下代碼

    Mybatis第三方PageHelper分頁插件怎么用

    攔截器鏈

    而這個PageHelper中的plugin方法是實現自Interceptor攔截器接口,所以會有一個地方統一調這個方法,往上追溯就會發現是在org.apache.ibatis.plugin.InterceptorChain攔截器鏈中調用的,如下。

    Mybatis第三方PageHelper分頁插件怎么用

    該類有一個List保存所有攔截器,還有三個方法,分別是pluginAll用于調用所有攔截器的plugin方法,addInterceptor添加攔截器,getInterceptors獲取攔截器鏈。

    看到這大致明白了它的原理,PageHelper通過實現Mybatis的Interceptor接口實現分頁,Mybatis通過InterceptorChain調用所有Interceptor。

    加載&調用攔截器

    那么我們看看Mybatis的攔截器是什么時候添加到攔截器鏈,什么時候被調用的。

    通過代碼追溯,發現在Configuration的addInterceptor方法中調用添加方法,Configuration.addInterceptor是在XMLConfigBuilder的pluginElement方法中被調用

    Mybatis第三方PageHelper分頁插件怎么用

    Mybatis第三方PageHelper分頁插件怎么用而XMLConfigBuilder是解析XML方式的Mybatis的配置的,顧名思義pluginElement方法是解析XML中plugin相關的配置節點的

    Mybatis第三方PageHelper分頁插件怎么用

    而我們確實在XML中配置了plugin

    Mybatis第三方PageHelper分頁插件怎么用

    所以我們現在知道了mybatis的攔截器是在Mybatis解析配置文件時,解析plugins節點時添加到InterceptorChain中的。

    攔截器什么時候調用的。我們看InterceptorChain的pluginAll方法在哪調的,通過代碼追蹤有如下四個地方調用攔截器鏈

    Mybatis第三方PageHelper分頁插件怎么用

    @Intercepts注解

    而PageHelper這個攔截器,我們可以發現這個類上有一個@Intercepts注解,這個注解接收的值為@Signature注解,在Signature注解配置了,Executor.class,query還有四個class:MappedStatement.class, Object.class, RowBounds.class, ResultHandler.class。

    Mybatis第三方PageHelper分頁插件怎么用

    了解Mybatis的插件機制的就明白了,這一行配置的意思是攔截Executor中的query方法,方法參數列表類型是MappedStatement.class, Object.class, RowBounds.class, ResultHandler.class,就是下面這個方法。

    Mybatis第三方PageHelper分頁插件怎么用

    所以看到這,我們可以斷定InterceptorChain的pluginAll方法在上述調用點的第四個,也就是org.apache.ibatis.session.Configuration#newExecutor(org.apache.ibatis.transaction.Transaction, org.apache.ibatis.session.ExecutorType),可想而知newExecutor,也就是創建Executor實例,可以斷定,創建Executor時通過PageHelper的plugin方法包裝了Executor,返回的是Executor的代理類。下面會講到創建動態代理。

    Mybatis第三方PageHelper分頁插件怎么用

    Mybatis第三方PageHelper分頁插件怎么用通過PageHelper創建代理對象

    我們在正向回顧一下,如何調到PageHelper的。首先進入到pluginAll

    Mybatis第三方PageHelper分頁插件怎么用

    然后會調到PageHelper的plugin方法,內部又調Plugin的warp方法

    Mybatis第三方PageHelper分頁插件怎么用

    我們看看Plugin.wrap方法干了啥,代碼如下。代碼跟過來我們知道現在的target是Executor,interceptor是PageHelper。首先獲取PageHelper攔截信息,然后篩選target是否是需要攔截的類型,這里會進入if判斷邏輯,返回Executor的代理對象。

    Mybatis第三方PageHelper分頁插件怎么用

    所以這時創建的Executor實例是代理對象,那么就會在某個時候調用代理的invoke方法(org.apache.ibatis.plugin.Plugin#invoke),invoke調Interceptor攔截器的intercept方法,從而調PageHelper的intercept方法執行分頁邏輯

    org.apache.ibatis.plugin.Plugin#invoke ==》 com.github.pagehelper.PageHelper#intercept

    攔截器的調用源頭-動態代理

    因為返回的是Executor的動態代理,所以肯定是調用Executor的某個方法時觸發進到invoke方法,具體在哪調的不好找。我們通過打斷點的方式看是從哪進invoke方法的,首先斷點打到Plugin的invoke方法內

    Mybatis第三方PageHelper分頁插件怎么用

    通過調用棧看到是org.apache.ibatis.session.defaults.DefaultSqlSession#selectList(java.lang.String, java.lang.Object, org.apache.ibatis.session.RowBounds)調過來的,在invoke方法內判斷了目標方法是不是我們要攔截的方法,因為PageHelper上注解的也是攔截這個方法,所以會進入到Plugin的invoke方法的第61行。所以就會進入到PageHelper的intercept方法,執行具體的攔截邏輯。

    分頁邏輯

    思路就是拼SQL。

    通過代碼跟蹤,最終的分頁邏輯是在com.github.pagehelper.util.SqlUtil#doIntercept方法中,第162行,獲取分頁SQL,

    調用

    com.github.pagehelper.dialect.AbstractDialect#getPageSql(org.apache.ibatis.mapping.MappedStatement, org.apache.ibatis.mapping.BoundSql, java.lang.Object, org.apache.ibatis.session.RowBounds, org.apache.ibatis.cache.CacheKey)

    Mybatis第三方PageHelper分頁插件怎么用

    com.github.pagehelper.dialect.AbstractDialect#getPageSql(org.apache.ibatis.mapping.MappedStatement, org.apache.ibatis.mapping.BoundSql, java.lang.Object, org.apache.ibatis.session.RowBounds, org.apache.ibatis.cache.CacheKey)中調用com.github.pagehelper.dialect.AbstractDialect#getPageSql(java.lang.String, com.github.pagehelper.Page, org.apache.ibatis.session.RowBounds,org.apache.ibatis.cache.CacheKey),是一個抽象方法,具體實現有好多種

    Mybatis第三方PageHelper分頁插件怎么用

    我們看mysql的,在原始SQL 拼接了" limit ?,?"

    Mybatis第三方PageHelper分頁插件怎么用

    關于“Mybatis第三方PageHelper分頁插件怎么用”這篇文章就分享到這里了,希望以上內容可以對大家有一定的幫助,使各位可以學到更多知識,如果覺得文章不錯,請把它分享出去讓更多的人看到。

    向AI問一下細節

    免責聲明:本站發布的內容(圖片、視頻和文字)以原創、轉載和分享為主,文章觀點不代表本網站立場,如果涉及侵權請聯系站長郵箱:is@yisu.com進行舉報,并提供相關證據,一經查實,將立刻刪除涉嫌侵權內容。

    AI

    乌兰县| 且末县| 安阳县| 扎赉特旗| 昔阳县| 万荣县| 泾川县| 金昌市| 和平区| 梧州市| 乐安县| 辽阳县| 咸宁市| 杂多县| 呼玛县| 廉江市| 华池县| 乡宁县| 神农架林区| 天台县| 湘潭县| 赫章县| 贵南县| 镇原县| 平塘县| 泸州市| 泸水县| 綦江县| 平邑县| 宣城市| 马公市| 崇阳县| 稷山县| 黄梅县| 曲阳县| 凭祥市| 三河市| 济宁市| 滨海县| 海口市| 阜新|