入門
PageHelperは良いMyBatisの改ページのプラグインです。簡易な構成の後に、コードのわずか数行は、ページングクエリを達成することができます。
データベースのデータを次のように:
@RequestMapping( "/ findAllUser")
公共のResponseResult <PageBean> findAllUser2(PageModel pageModel){
PageHelper.startPage(pageModel.getPageNum()、pageModel.getPageSize())。
PageHelper.orderBy( "IDのDESC")。
一覧<MyUserと> myUsers = myUserServices.selectUser();
PageBean <MyUserと> pageBean =新しいPageBean <>(myUsers)。
新しいのResponseResult <>(200、 "成功"、pageBean)を返します。
}
コードは、ちょうど現在、MyBatisののクエリページネーションを実現することができる必要としていたページあたりのページ数の大きさではなく、奇妙渡さ見えます。ほかにも、昇順と降順を達成することができます。
- それはどのようにそれをするのでしょうか?あなたは、動的プロキシを使用していますか?
- これは、SQLを介してページングを実装するのですか?
- PageHelper.startPageは()にThreadLocalを使用していませんか?ThreadLocalの値の内側にリリースされたとき?これはThreadLocalのメモリリークが発生しますか?
私は、ソースコード解析持っていたこれらの質問では、この記事では、設定するには、ページング機能を実装方法については説明しません、コードはここからダウンロードすることができます。 https://github.com/pmh905001/freedom-20200203springboot
主にソースコード解析にこの記事からいくつかのアイデアを学ぶことができPageHelperの原則の実現を探求します。
入手
原則PageHelperそれの実現を開始する方法の分析?
現在のコードは、コントローラ--->サービスである--->マッパーは、単に数行のコードは、このメソッドを除外するために、達成するために内部のトラックを見ることができません。
pageSizeを、PageHelper.startPage設定し、そのコード(pageModel.getPageNum()、pageModel.getPageSizeは())ので、それはそれを使用する場所を持っている必要があり、私たちは、この方法がここに追跡することができ従ってください
PageHelper原理分析
実際に私の3番目の質問に答えるされてここを参照してください:PageHelper.startPageは()ThreadLocalを使用していませんか?はい、それはThreadLocalを使用することです。
その後、我々は、我々は、トレースブレークポイントを行うためのPageSizeにあり、この分野です。次のように私たちは、コールスタックを取得することができます。
私たちは、MyBatisのSQLのPageInterceptorが実行されているという名前のプロキシクラスが傍受された最初のクエリの合計数を見つけ、その後、ページングクエリを実行することができます。
そして、私たちは、この動的プロキシクラスは、クエリメソッド内キュータクラスインターセプトされ、次のステートメントから見ることができます。
ここでの分析は、実際に私の最初の質問に答えました。
- それはどのようにそれをするのでしょうか?あなたは、動的プロキシを使用していますか?
彼は動的プロキシExecutor.query()メソッドによって遮断されました。そして、彼は自分自身のJavaの動的プロキシの実装を持参してください。
PageInterceptorを分析することにより、我々はまた、質問2に答えることができます。
2.それは、SQLを介してページングを実装するのですか?
それはここでは詳細に説明されていない、SQLを介してページングを実装することです。
他の
もう一つの問題は、我々はPageHelperはそれを解放するためにページング情報を配置するもの、その後、ThreadLocalを経由ページング情報を設定することで見ているのですか?それとも、メモリリークが発生することがあります。
PageHelper里面有一个clearPage()方法,反向查看调用点即可以知道程序在哪儿释放分页信息。
从上面的代码可以看出,拦截器执行完毕之后最终会释放分页信息。并且放在finally块中,可以保证不会出现ThreadLocal内存泄漏。
还有一个问题,Mybatis是否支持Executor多个拦截器,比如:分页拦截器和排序拦截器,答案是肯定的。Mybatis使用提供了一种插件的机制,读者可以参考一下InterceptorChain.pluginAll()方法。
这里代码有点绕,我之前看到这里感觉很别扭,这应该只返回一个动态代理类,怎么会支持多层拦截呢? 实际上这里代码写的很精炼,每一次循环相当于被代理上面套了一层,第二次循环就会再在动态代理类基础上再封装一层.