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

推薦する

Vue における属性とプロパティの具体的な使用法と違い

目次Vue.jsにおける属性とプロパティ値および関連する処理として属性とプロパティの概念属性とプロパ...

React を使って小さなプログラムを書くための Remax フレームワークのコンパイル プロセス分析 (推奨)

Remax は、実行時に構文制限のないソリューションを採用した React を使用して小規模なプロ...

MySQL で sum 関数を使用する例のチュートリアル

導入今日は、MySQL の sum 関数の使い方を紹介します。この関数は、MySQL データベースを...

CentOS 7.6 Telnetサービス構築プロセス(Opensshアップグレードバトル第一弾のバックアップトランスポートライン構築)

不明な点があるときはいつでも、Blog Park にアクセスして、いつでも答えやインスピレーションを...

CSS3 はクールな 3D 回転遠近法効果を実現します

CSS3はクールな3D回転パースペクティブを実現します3D アニメーション効果はますます人気が高まっ...

デジタルテーブル特殊効果を実現するネイティブJS

この記事では、ネイティブ JS で実装されたデジタル時計エフェクトを紹介します。エフェクトは次のとお...

Nginx で同じドメイン名を持つ複数のプロジェクトを構成する方法

Nginx を使用して同じドメイン名で複数のプロジェクトを構成するには、次の 2 つの方法があります...

設定ファイルを変更した後、操作を再開します

余計なことは言わないで、コードだけ見てみましょう〜 # docker-compose をダウン # ...

Vue で親コンポーネントから子コンポーネントにデータを渡すいくつかの方法

最近、Vue のソースコードを勉強していて、Vue で親コンポーネントと子コンポーネント間でデータを...

HTML と CSS を書くための 6 つの最も効果的な方法

この記事では、効率を向上させ、時間を節約することを願って、最も効果的な 6 つの方法を紹介します。 ...

MySQLクエリ条件のnot inとinの違いと理由

まずSQLを書く SELECT DISTINCT from_id タラから cod.from_id ...

Linuxでプロセスが占有するポート番号を表示する

Linux システム管理者にとって、サービスがポートに正しくバインドされているか、またはポートをリッ...

JavaScript で実装された 7 つのソート アルゴリズムの概要 (推奨!)

目次序文バブルソート基本アルゴリズム2 番目の書き方は、基本的なアルゴリズムに基づいて改良されていま...

UTF8 でエンコードされた Web ページにファイルが含まれている場合の、ページの前の空白行の解決方法

<br />このページはUTF8エンコードを使用しており、ヘッダーとフッターはテンプレー...

Xtrabackup を使用して MySQL をバックアップおよび復元する方法

目次1. バックアップ1.1 万全の準備1.2 追加の準備2 バックアップとリカバリ2.1 データの...