質問をすることでしか得られない、回答やアドバイスがある。

15分調べてもわからないことは、質問しよう!

ただいまの
回答率

88.82%

JavaインターフェースおよびSpringのPage<T>の扱いについて

解決済

回答 1

投稿 編集

  • 評価
  • クリップ 1
  • VIEW 986

kane5111

score 70

質問内容 

下記を前提と致します。
・webアプリを対象としています
・コーティングの方法ではなく、各項目に対する認識や理解の部分についてお尋ねしております

  1. インターフェースのメソッドについて
    JpaRepmsitoryなどのインターフェース(上位のインターフェース含む)に定義されたメソッド(find,save等)の処理内容は何処にあるのでしょうか?
    今の私の理解度だと、JpaRepmsitoryを実装した具象クラスがどこかにあり、そのクラスに処理内容が定義されていると思っているのですがこの点は間違いないでしょうか?
    (インターフェースについて上記理解で間違い無いかの確証が欲しいです)

  2. find()について
    find...By...()はインターフェース側にメソッド定義するだけで、条件指定の検索が行えますが、どうやってこれが実現されているのかさっぱりわかりません。
    メソッド名から文字抽出して、処理に反映させるなんてことが出来るのでしょうか?

  3. Page<T>について
    ページネーションを実現する際に使用していますが、感覚としてListなどのコレクションにページ番号などのフィールドが定義されたようなものといった認識でも良いのでしょうか?
    また、画面の各ページリンクからControllerへ遷移する時、一緒にリクエストパラメータにページ番号を付けて送りますが、受取側のControllerに受け取る為の変数を用意していないのに、ページが正常に切り替わります。Page<T>実装クラスが勝手に受け取っているのでしょうが、具体的にどの様に実現されているのでしょうか?

昨日からspringを業務で使う様になりましたが、初めて目にするものばかりで理解が追いついておりません。
初歩的な質問ばかりではありますが何卒宜しくお願い致します。

Page<T>について(自己解決)

・Pageは、<T>オブジェクトリスト(Listでは無い)のサブリストである。Listのget/addの様に1つの要素にアクセスする方法があるのかは分からないが、Iterable<T>インターフェースを継承しているため、for-eachでアクセスは可能である。
・RDBからPageを取得するイメージとして、まずJPAなどにより検索条件に合致した(もしくは全レコード)仮のリスト(ORM)を取得して、このリストから指定したページ情報分のPageを作成する?

リクエストパラメータのページ情報について(Pageable)

結論として、コントローラの引数に指定していたPageableが勝手に取得してくれていた。PageableはPage関連のページ情報を受渡しするオブジェクトであり、実装クラスとしてPageRequestがある。
Pageableが取得してくれるリクエストパラメータは決まっており、
"page","size","sort"などがある。

  • 気になる質問をクリップする

    クリップした質問は、後からいつでもマイページで確認できます。

    またクリップした質問に回答があった際、通知やメールを受け取ることができます。

    クリップを取り消します

  • 良い質問の評価を上げる

    以下のような質問は評価を上げましょう

    • 質問内容が明確
    • 自分も答えを知りたい
    • 質問者以外のユーザにも役立つ

    評価が高い質問は、TOPページの「注目」タブのフィードに表示されやすくなります。

    質問の評価を上げたことを取り消します

  • 評価を下げられる数の上限に達しました

    評価を下げることができません

    • 1日5回まで評価を下げられます
    • 1日に1ユーザに対して2回まで評価を下げられます

    質問の評価を下げる

    teratailでは下記のような質問を「具体的に困っていることがない質問」、「サイトポリシーに違反する質問」と定義し、推奨していません。

    • プログラミングに関係のない質問
    • やってほしいことだけを記載した丸投げの質問
    • 問題・課題が含まれていない質問
    • 意図的に内容が抹消された質問
    • 過去に投稿した質問と同じ内容の質問
    • 広告と受け取られるような投稿

    評価が下がると、TOPページの「アクティブ」「注目」タブのフィードに表示されにくくなります。

    質問の評価を下げたことを取り消します

    この機能は開放されていません

    評価を下げる条件を満たしてません

    評価を下げる理由を選択してください

    詳細な説明はこちら

    上記に当てはまらず、質問内容が明確になっていない質問には「情報の追加・修正依頼」機能からコメントをしてください。

    質問の評価を下げる機能の利用条件

    この機能を利用するためには、以下の事項を行う必要があります。

質問への追記・修正、ベストアンサー選択の依頼

  • m.ts10806

    2019/05/09 20:07

    質問が広範囲すぎて回答の方向性が難しいです。
    タイトルも含めてもっとピンポイントに要件を絞られては?
    Springとはいえ、Web系とそうでないもの、細かいプロダクトにわかれてたりするので、それも含めて具体的に記載してください

    キャンセル

回答 1

checkベストアンサー

+1

1について

そのとおりです。

2について

Springの実装詳細を自分は知りません。が、Javaで何ができ得るかについてコメントしてみます。
Spring Data JPAには、Repositoryインターフェースに宣言されたメソッドを、その名前からクエリを生成して自動的に生成してくれる機能があるとのことです。実装の仕方は色々考えられますが例えばjava.lang.reflect.Proxyというクラスを利用すると次のようなことができます。

(1) 特定の(複数の)インターフェースとInvocationHandlerを指定してインスタンスが作れる。
(2) そのインスタンスは指定したインターフェースを実装(interface Xxx implements I1, I2, ... のように宣言したクラスXxxであるかのように)している。
(3) そのインスタンスに対してインターフェースで規定されたメソッドを呼び出すことができる
(4) そのメソッドを呼び出すとProxyの内部機構を介して(1)で指定したInvocationHandlerインスタンスのinvokeメソッドの呼び出しに(自動的に)置き換わってくれる。

InvocationHandler#invokeメソッドへはProxyインスタンスや呼び出されたメソッドを表すメタ情報(java.lang.reflect.Method)や渡された引数が渡されます。よってInvokeを実装するプログラマーは

findByLastnameAndFirstname

なんていう名前のメソッドが呼び出されたときメソッドの名前をjava.lang.reflect.Methodから取り出して

えーと最初が"findBy"でその後に"Lastname"と"And"と"Firstname"が続いているからDBの検索条件のQUERYを「… where e.lastname = ?1 and e.firstname = ?2」という具合にして、このメソッドに渡された2つの引数をQueryの引数として指定する

なんてことが実装できます。このあたり(InvocationHandler)はアプリケーション開発者が作る必要はなくSpringフレームワークのランタイムとして実装されていると思います。

ちなみにProxyを利用して実装しているなら、多分Invokeが呼び出されたときに一々メソッド名を解析するのではないでしょう。あらかじめインターフェース上にあるメソッド一覧を調べて各メソッドに必要なQueryのテンプレートなりを準備した上でInvokeされたら最小限の手間でqueryを生成(発行?)するようになっているのだろうと想像します。


3について、自分はSpringについて名前ぐらいしか知らないので他の方の回答に期待します。

投稿

編集

  • 回答の評価を上げる

    以下のような回答は評価を上げましょう

    • 正しい回答
    • わかりやすい回答
    • ためになる回答

    評価が高い回答ほどページの上位に表示されます。

  • 回答の評価を下げる

    下記のような回答は推奨されていません。

    • 間違っている回答
    • 質問の回答になっていない投稿
    • スパムや攻撃的な表現を用いた投稿

    評価を下げる際はその理由を明確に伝え、適切な回答に修正してもらいましょう。

  • 2019/05/09 23:49

    ちなみに 2は命名規則通りにインタフェースを作成すると実行時に勝手にクラスが作られるw CGLIB

    キャンセル

  • 2019/05/10 02:37

    Proxy.newProxyInstanceの例でもそうなり、インターフェースのクラスオブジェクトを指定するとそれを実装したクラスとそのインスタンスを生成してくれるので使う方にとってはあっけないくらい簡単です。
    InvocationHandlerやらアノテーションやらを提供する方(フレームワーク側)はリフレクションでメタ情報(メソッド名や引数情報など)を調べるなどそこそこ面倒なことが必要ですがその気になれば色々なものが作れそうです。質問者さんが「メソッド名から文字抽出して、処理に反映させるなんてことが出来るのでしょうか?」とおっしゃってますがまさにそういうことをしていると思います。

    キャンセル

  • 2019/05/10 06:56

    ご回答頂きありがとうございます。
    お陰様で疑問点を解消することができました。
    ProxyやInvocationHandler自体についてはもっと勉強が必要そうではありますが、私がこれらを使用するのはまだまだ先の話になりそうです。
    ただ、裏側の動きを含め全体の流れを知ることが出来た為、魔法を使っている気持ち悪さは無くなりました笑。
    また、.classやrefrectについても勉強する良い機会になりました。

    非常に分かり易い説明ありがとうございました!

    キャンセル

15分調べてもわからないことは、teratailで質問しよう!

  • ただいまの回答率 88.82%
  • 質問をまとめることで、思考を整理して素早く解決
  • テンプレート機能で、簡単に質問をまとめられる

関連した質問

同じタグがついた質問を見る