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 サーバーを構築する方法の詳細な説明 (成功保証)

推薦する

コネクタコンポーネントから Tomcat のスレッドモデルを見る - BIO モード (推奨)

Tomcat の上位バージョンでは、デフォルト モードは NIO モードを使用することになります。...

シンプルなウェブ計算機を実装するJavaScript

背景私は新しいプロジェクト チームに配属されたので、プロジェクトでは js を使用する必要があります...

登録フォームのデザインルール

随分前に「Patterns for Sign Up & Ramp Up」を読み終えました。今...

nuxt.js 複数の環境変数の設定

目次1. はじめに2. シナリオ3. 環境を整える3.1 環境変数の挿入4. 最後に1. はじめに一...

フレックスレイアウトの改行スペースでの align-content の使用

1. この記事で実装した効果図は以下のとおりです。レイアウトの右側に Flex レイアウトを使用し、...

Dockerネットワーク作成に--subnetを追加した後の問題を解決する

Docker ネットワークの作成に –subnet を追加した後、docker network ls...

Dockerコンテナのホスト間通信におけるダイレクトルーティングの詳細な説明

概要Docker 自体の現在のデフォルト ネットワークについては、単一ホスト上の異なる Docker...

CSS の複雑なセレクターと CSS のフォントスタイルと色属性の詳細な説明

これまでに CSS の基本的なセレクターをいくつか学習しましたが、今日は CSS の複雑なセレクター...

MySQLデータベースで外部キー制約を使用する必要があるかどうかの詳細な説明

1. はじめに外部キー制約を使用するかどうかという話題は、すでに決まり文句になっています。学校では、...

Linux カーネル デバイス ドライバー カーネル リンク リストの使用上の注意

/******************** * カーネルにおけるリンクリストの応用********...

CSS を使用して固定ナビゲーションと左右スライドを備えたスクロール バーを作成する方法

上に示すように、ナビゲーションは上部に固定されており、左右にスライドしてさらにオプションをクリックで...

MySQL テーブルの垂直分割と水平分割

垂直分割垂直分割とは、データテーブルの列を分割すること、つまり、多くの列を持つテーブルを複数のテーブ...

CSS3を使用してオンラインライブ放送に似たキューアニメーションを実装する方法

以前、グループの友人が質問しました。つまり、ミニプログラムでユーザーがオンラインになったときに、ライ...

docker ベースで Prometheus+Grafana を構築する手順の詳細説明

1. プロメテウスの紹介Prometheus は、もともと SoundCloud によって開発された...

Tomcat サーバーの応答が遅い場合の解決策

1. 分析的思考1. 機械自身の理由を排除する2. サーバーパフォーマンス分析3. プロジェクト自体...