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 でテーブルスペースの断片化を解消する詳細な例

MySQL でテーブルスペースの断片化を解消する詳細な例断片化の原因(1)テーブルのストレージは断片...

MySQL ユーザー権限管理の実装

1. MySQL の権限の概要MySQL には、権限を制御する 4 つのテーブルがあります。user...

Dayjs を使用して Vue で一般的な日付を計算する方法

vue を使用してプロジェクトを開発する場合、フロントエンドでは次のような日付と時刻を計算する必要が...

JavaScript プログラムのループ構造の詳細な説明

目次構造を選択ループ構造その間…しながらforループ…のために…で…の…のためにまとめループの終了壊...

Linuxでサーバーのハードウェア情報を表示する方法

みなさんこんにちは。今日は12連休ですが、何かお買い物はしましたか?今日は「Linux View S...

ピクセルを包括的なブランド体験に変えるヒント

編集者:この記事では、インタラクティブデザインがブランドコミュニケーションチェーン全体で果たすべき役...

画像ボタン送信とフォーム繰り返し送信の問題に関する議論

多くの場合、フォームを美しくするために、送信ボタンが画像に置き換えられます。ただし、細部に注意を払わ...

Linux mysql5.5 を mysql5.7 にアップグレードする手順と落とし穴

目次Linux MySQL 5.5 が MySQL 5.7 にアップグレードされました1. mysq...

MySQL インデックスに関するヒントのまとめ

目次1. インデックスの基礎知識1.1 インデックスの利点1.2 インデックスの有用性1.3 インデ...

MySQLウィンドウ関数の具体的な使用法

目次1. ウィンドウ関数とは何ですか? 1. ウィンドウをどのように理解しますか? 2. ウィンドウ...

AngularとIonicのライフサイクルとフック関数を素早く理解するための記事

目次角度成し遂げる呼び出し順序知らせイオニックionic はページのライフサイクルをどのように処理し...

CentOS7環境にMySQL5.5データベースをインストールする

目次1. 現在のシステムにMySQLがインストールされているかどうかを確認する2. インストールされ...

MySQL 5.7.16 ZIP パッケージのインストールと設定のチュートリアル

この記事では、MySQL 5.7.16 ZIPパッケージのインストールと設定のチュートリアルを参考ま...

CSS を使用して波状のウォーターボール効果を実装するためのサンプルコード

今日は新しいCSS特殊効果、波型ウォーターボール効果を学びました。これもとても美しいです HTML:...

Enterキーを押すとフォームが自動的に送信されます。予期せぬ発見

コードをコピーコードは次のとおりです。 <!DOCTYPE html> <html...