MyBatisインターセプターのページング機能を実装する方法

MyBatisインターセプターのページング機能を実装する方法

MyBatisインターセプターのページング機能を実装する方法

序文:

まず、実装原則についてお話しします。インターセプターを使用して元の SQL をインターセプトし、ページング クエリのキーワードと属性を追加して新しい SQL ステートメントに組み立て、mybatis に渡して実行します。

ビジネス コード以外に記述する内容はそれほど多くありませんが、重要なものをいくつか挙げます。

1. ページングオブジェクトのページクラス。オブジェクトに 2 つのパラメータ (現在のページ番号 (フロントエンドによって指定) とレコードの合計数 (インターセプターで割り当てられる)) を設定すると、ページング SQL ステートメントで使用される 2 つのパラメータを計算するのに役立ちます。

/**
 * ページングに対応するエンティティクラス */
パブリッククラス Page {
  /**
   * エントリー総数*/
  プライベート int 合計数​​;
  /**
   * 現在のページ */
  プライベート int 現在のページ;
  /**
   * 総ページ数*/
  プライベート int totalPage;
  /**
   * 1ページあたりのエントリ数*/
  プライベート int ページ番号 = 5;
  /**
   * エントリを取得するデータベースの制限パラメータ*/
  プライベート int dbIndex;
  /**
   * データベースの制限パラメータ、合計でいくつのエントリが取得されるか */
  プライベート int dbNumber;

  /**
   * 現在のオブジェクト内の属性値に応じて関連する属性値を計算して設定します*/
  パブリックボイドカウント(){
    // ページの総数を計算します int totalPageTemp = this.totalNumber / this.pageNumber;
    int プラス = (this.totalNumber % this.pageNumber) == 0 ? 0 : 1;
    合計ページ温度 = 合計ページ温度 + プラス;
    合計ページ温度が 0 の場合
      合計ページ温度 = 1;
    }
    this.totalPage = 合計ページ温度;

    // 現在のページ番号を設定します // 総ページ数が現在のページ数より少ない場合、現在のページ番号を総ページ数に設定する必要があります if (this.totalPage < this.currentPage) {
      this.currentPage = this.totalPage;
    }
    // 現在のページ番号が1未満の場合、1に設定します
    現在のページが 1 未満の場合
      this.currentPage = 1;
    }

    //制限パラメータを設定する this.dbIndex = (this.currentPage - 1) * this.pageNumber;
    this.dbNumber = this.pageNumber;
  }

  パブリック int getTotalNumber() {
    合計数を返します。
  }

  パブリック void setTotalNumber(int totalNumber) {
    this.totalNumber = 合計数;
    これをcount()します。
  }

  パブリック int getCurrentPage() {
    現在のページを返します。
  }

  パブリック void setCurrentPage(int currentPage) {
    this.currentPage = 現在のページ;
  }

  パブリック int getTotalPage() {
    totalPage を返します。
  }

  パブリック void setTotalPage(int totalPage) {
    this.totalPage = 合計ページ;
  }

  パブリック int getPageNumber() {
    ページ番号を返します。
  }

  パブリック void setPageNumber(int ページ番号) {
    this.pageNumber = ページ番号;
    これをcount()します。
  }

  パブリック int getDbIndex() {
    dbIndex を返します。
  }

  パブリック void setDbIndex(int ​​dbIndex) {
    this.dbIndex = dbIndex;
  }

  パブリック int getDbNumber() {
    dbNumber を返します。
  }

  パブリック void setDbNumber(int dbNumber) {
    this.dbNumber = dbNumber;
  }
}

2. キーインターセプターの実装

パッケージ com.imooc.interceptor;

java.sql.Connection をインポートします。
java.sql.PreparedStatement をインポートします。
java.sql.ResultSet をインポートします。
java.util.Map をインポートします。
java.util.Properties をインポートします。

org.apache.ibatis.executor.parameter.ParameterHandler をインポートします。
org.apache.ibatis.executor.statement.StatementHandler をインポートします。
org.apache.ibatis.mapping.BoundSql をインポートします。
org.apache.ibatis.mapping.MappedStatement をインポートします。
org.apache.ibatis.plugin.Interceptor をインポートします。
org.apache.ibatis.plugin.Intercepts をインポートします。
org.apache.ibatis.plugin.Invocation をインポートします。
org.apache.ibatis.plugin.Plugin をインポートします。
org.apache.ibatis.plugin.Signature をインポートします。
org.apache.ibatis.reflection.DefaultReflectorFactory をインポートします。
org.apache.ibatis.reflection.MetaObject をインポートします。
org.apache.ibatis.reflection.SystemMetaObject をインポートします。

com.imooc.entity.Page をインポートします。

/**
 * ページングブロッカー * 
 * @author スカイ
 *
 */
@インターセプト({
    @Signature(type = StatementHandler.class、method = "prepare"、args = { Connection.class、Integer.class }) })
パブリッククラス PageInterceptor は Interceptor を実装します {

  パブリックオブジェクトインターセプト(呼び出し呼び出し)はThrowableをスローします{
    ステートメント ハンドラ statementHandler = (ステートメント ハンドラ) invocation.getTarget();
    MetaObject metaObject = MetaObject.forObject(statementHandler, SystemMetaObject.DEFAULT_OBJECT_FACTORY,
        SystemMetaObject.DEFAULT_OBJECT_WRAPPER_FACTORY、新しい DefaultReflectorFactory());
    MappedStatement マップされたステートメント = (MappedStatement) metaObject.getValue("delegate.mappedStatement");
    //MetaObject メタデータを通じてメソッド名 ID を取得します: com.XXX.queryMessageListByPage
    文字列 id = mapstedStatement.getId();
    //mybatisで定義されたページングに関連するクエリIDを一致させる
    idが一致する場合(".+ByPage$"){
      //BoundSql には元の SQL ステートメントと対応するクエリ パラメーターが含まれます。BoundSql boundSql = statementHandler.getBoundSql();
      Map<String, Object> パラメータ = (Map<String, Object>) boundSql.getParameterObject();
      ページ page = (Page) params.get("page");
      文字列 sql = boundSql.getSql();
      文字列 countSql = "count(*)from (" + sql + ")a を選択";
      接続 connection = (Connection) invocation.getArgs()[0];
      準備されたステートメント countStatement = connection.prepareStatement(countSql);
      ParameterHandler パラメータハンドラー = (パラメータハンドラー) metaObject.getValue("delegate.parameterHandler");
      パラメータハンドラ。countStatement パラメータを設定します。
      結果セット rs = countStatement.executeQuery();
      rs.next() の場合 {
        //なぜ getInt(1) なのでしょうか? データ テーブルの列は 1 からカウントが始まるためです。page.setTotalNumber(rs.getInt(1));
        System.out.println("インターセプターは、ページ内のレコードの合計数が次の数であることを認識します: " + page.getTotalNumber());
      }
      文字列 pageSql = sql + " limit " + page.getDbIndex() + "," + page.getDbNumber();
      metaObject.setValue("delegate.boundSql.sql", pageSql);
    }
    呼び出し.proceed() を返します。
  }

  /**
   * @param ターゲット
   * 傍受されるオブジェクト */
  パブリックオブジェクトプラグイン(オブジェクトターゲット) {
    // インターセプター クラスを、他の人に代わってチケットを購入する会社に例えると、これは他の人に代わってチケットを購入するエージェントです (メソッドに入る前は、他の人に代わってチケットを購入する機能を持たないエージェントですが、メソッドに入った後は、他の人に代わってチケットを購入する機能を持つエージェントになります)
    // アノテーションを通じてインターセプト対象の情報を取得します。インターセプト要件を満たしていない場合は、元のターゲットを返します。要件を満たしている場合は、動的プロキシを使用してプロキシ オブジェクトを生成します。 return Plugin.wrap(target, this);
  }

  パブリック void setProperties(プロパティ プロパティ) {
    // TODO 自動生成されたメソッドスタブ

  }

}

3. mybatis-config.xmlに独自のインターセプターを登録する

 <!-- カスタマイズされたページングインターセプター-->
  <プラグイン>
    <plugin interceptor="作成したインターセプターの完全なクラス名">
    </プラグイン>
  </プラグイン>

Dao レイヤーに関連する mapper.xml 内の SQL ステートメントを変更する必要はありません。

4. フロントエンドは、表示するページのパラメータをバックエンドに渡す必要があります。サービス層を通じてクエリパラメータを組み立てた後、ページングデータをクエリするために MyBatis に渡されます。私が定義したページング DAO インターフェイスによって返されるデータは、ページングクエリの結果を含むリストです。フロントエンドでは、jquery_pagination プラグインを使用してページネーション表示を実装できます。設定方法については、公式 github をご覧ください。

<!-- ページネーションに必要なスクリプト -->
<%
  // リクエストコンテキストを取得します。String context = request.getContextPath();
%>
<link href="../css/pagination.css" rel="外部nofollow" rel="スタイルシート" type="text/css"/>
<script type="text/javascript" src="../js/jquery-1.11.3.js"></script>
<script type="text/javascript" src="../js/jquery.pagination.js"></script>
<script type="text/javascript">

//ページネーションボタンをクリックした後にトリガーされるアクション function handlePaginationClick(new_page_index, pagination_container) {
<!-- stuForm フォームから現在のページのパラメータを送信します。restful メソッドを使用すると、springmvc が @PathVariable キーワードで定義されたパラメータを使用して接続できるようになります。これら 2 つのパラメータはページング コントロール自体によって提供されるため、自分で見つける必要はありません。ただし、カウントは 0 から始まり、バックグラウンド ページング カウントは 1 から始まるため、手動で 1 を追加する必要があります。 -->
  $("#stuForm").attr("action", "定義したページングクエリ URL/"+(new_page_index+1));
  $("#stuForm").submit();
  false を返します。
}

$(関数(){
  $("#ニュースページネーション").pagination(${result.totalRecord}, ​​{
    items_per_page:${result.pageSize}, // ページあたりに表示されるレコード数 current_page:${result.currentPage} - 1, // 現在表示されているデータのページ num_display_entries:8, // ページに表示されるエントリ数 next_text:"次のページ",
    prev_text: "前のページ",
    num_edge_entries:2, // ページネーション本体に接続し、表示されるエントリの数を表示します callback:handlePaginationClick(現在のページ、ページネーション div の ID), // コールバック関数を実行します load_first_page:false // ページが常に更新されないようにします (これは非常に重要です!)
  });
});
</スクリプト>
<!-- この部分では、c:forEach タグを使用してクエリ結果テーブルを出力します -->
<!--ページング コントロール名-->
<div id="ニュースページネーション"></div>

この概要を書く目的は、ページング機能(フロントエンドとバックエンドの両方をカバー)の全体的なソリューションを形成することです。 4 月 17 日と 18 日から、これまでの期間に学んだことを応用する小さなシステムを作成します。その後、この記事の誤った部分を更新するために戻ってきます。

ご質問がありましたら、メッセージを残すか、このサイトのコミュニティで議論してください。お読みいただきありがとうございます。お役に立てれば幸いです。このサイトをサポートしていただき、ありがとうございます!

以下もご興味があるかもしれません:
  • Mybatis Limitはページング機能を実装します
  • Mybatisは共同テーブルクエリとページング機能を実装します
  • Mybatis Plus ページング機能を実現するカスタムメソッドのサンプルコード
  • Spring MVC+MyBatis+MySQL でページング機能を実装する例
  • MyBatisインターセプターはページング機能の例を実装します
  • MyBatisはページングの実装方法を詳細に説明しています

<<:  Ubuntu Server でのワイヤレス ネットワーク カードの詳細な設定

>>:  Ubuntu で FTP サーバーを構築する方法の詳細な説明 (成功保証)

推薦する

MySQLインデックスに関する重要な面接の質問をいくつか共有します

序文インデックスは、データベース内の 1 つ以上の列の値を並べ替え、データベースが効率的にデータを取...

MySQL スライディング集計/年初来集計の原理と使用例の分析

この記事では、例を使用して、MySQL スライディング集計/年初来集計の原理と使用方法を説明します。...

Vue はモバイル端末にマルチグリッド入力ボックスを実装

最近、同社は、下図に示すように、h5 ページ操作を完了するという要件を提示しました。 ネットで入手で...

HTMLはBaidu百科事典のナビゲーションドロップダウンメニュー機能を模倣します

HTML は、Baidu 百科事典のナビゲーション ドロップダウン メニュー機能を模倣します。具体的...

jQueryはネストされたタブ機能を実装します

この記事では、ネストされたタブ機能を実装するためのjQueryの具体的なコードを参考までに紹介します...

uniappの無痛トークンリフレッシュ方法の詳細な説明

フロントエンドがインターフェースを要求すると、バックエンドでインターフェースが定義されます。ステータ...

JavaScriptのURLオブジェクトとは何かについて話しましょう

目次概要ハッシュプロパティホストプロパティホスト名属性Href属性起源のプロパティユーザー名とパスワ...

Windows 10 で Ubuntu 20.04 LTS をアップデートする方法

2020 年 4 月 23 日、本日、Windows 上の Ubuntu 20.04 では、Ubun...

フォーム送信の更新ページはソースコード設計にジャンプしません

1. ソースコードの設計コードをコピーコードは次のとおりです。 <!DOCTYPE html ...

Dockerコンテナの接続と通信の実装

ポート マッピングは、Docker を別のコンテナーに接続する唯一の方法ではありません。 Docke...

Linux で Hadoop クラスターをインストールするための詳細な手順

目次1. usrディレクトリにHadoopディレクトリを作成し、インストールパッケージをそのディレク...

幅と高さが可変の要素を中央に配置するための CSS ソリューション

1. 水平中央公開コード: html: <div class="parent&quo...

JavaScript のドキュメント オブジェクト モデル (DOM)

目次1. DOMとは何か2. 要素を選択する3. getElementById() 4. クエリセレ...

マインドマップを使って4つの側面からWeb標準の価値を議論する

このアイデアを改善し、より良い意見を得られることを期待して、議論を刺激するためにいくつかの値を大まか...

H5 WeChatパブリックアカウント認証を実装するための簡単な手順

序文昨日、h5 WeChat認証の実装が必要なプロジェクトがありました。したがって、この機能を完了す...