Skip to content

Instantly share code, notes, and snippets.

@keik
Last active August 29, 2015 14:10
Show Gist options
  • Save keik/15cf5da547b64c437fdc to your computer and use it in GitHub Desktop.
Save keik/15cf5da547b64c437fdc to your computer and use it in GitHub Desktop.
今すぐダウンロード

Springの抽象化技法(個人の意見です)

※ Spring 歴 2 週間です。

フルスタックフレームワークなので色んな技術要素があるが、抽象化手法のアプローチがそれぞれで異なり、当たり外れを感じる。

技術 つらみ(5段階) 詳細
Spring MVC (Spring Framework) 2 REST の原則を部分採用し、リクエストの処理を、URI・HTTPメソッド・パラメータの組み合わせに応じて振り分けることで、制御フローを制御する。URI に .json といった拡張子をつけることで特定のメディアタイプを要求する Content Negotiation 機能をあわせると、少ないルールで CRUD 処理、さらに画面遷移か Web サービスかを決定できる可能性があり、かつ実装の自由さは委ねられている。
AOP (Spring Framework) 1 特定の処理に追加処理を仕込むための条件をパターンマッチで定義し、また仕込むタイミングを 処理実行前処理実行後 など 5 種より選択することで、制御フローを制御する。
ルールがシンプルで、かつ仕込む処理内容は自由。
Spring Data JPA 5 ピュアな JPA との差分を理解していないが……。
データベースアクセスをJava のクラスへのアクセスに置き換える、というところまでは期待が高まるが、RDBMS の機能と一対一対応する勢いでアノテーションをつけたり、しまいには JQPL (Java Persistence query language) とかいう独自のクエリ言語を使う。
これ抽象化されてるの? 単なる知識の置き換えに思えるから、より汎用性の高い SQL を学ぼうと思った。
Spring Security 4 ユーザの ロール やリクエストされた URI パターンといったシンプルなルールで認可処理(アクセス権制御)を行ったり、役割に応じてレイヤ化された多層フィルタといった制御フローの提供によって、制御フローを制御する。
そこまではいいが、パスワード認証やベーシック認証といった認証方式ごとにフィルタがいたり、Remember me 機能用のフィルタがいたりと、妙なところが抽象化されていない。というか実装が多くて結局のところ何をやっていて何をやっていないのか分かりにくい。
Spring Boot ? 特定の Bean の存在有無に応じて、アノテーション済み設定クラスをロードする。設定の抽象化であり、IoC 的な観点での抽象化とは異なる。
大量のアノテーションやメタ・アノテーションをさらにラップしていて、もう全部アノテーションでコーディングしたらいいんじゃないかな。結局はソースコード読まないと実際のところ何してくれてるのか分からない、けど確かに調子よく動く。Java でプロトタイピングするにはぴったり。

J★P★A

Cascade Trap

@ManyToManyフィールドにcascade指定はトラップ。 CascadeType.REMOVE指定状態で片方のエンティティを削除すると、関連のあるエンティティ 本体* もすべて消える。

そうじゃない。エンティティと関連だけを消したいんだ。

/* BookとTagがManyToManyな場合に、Bookと関連を削除する例 */
public void deleteBooks(Integer bookId) {
    Book book = booksRepository.findOne(bookId);

    // 手動で関連を消す
    book.getTags().clear();

    // 関連を消したあとにエンティティを削除する
    booksRepository.delete(book);
}

わかるよ

Testing

どのようにして前提データを作るか?

ID に頼らない前提データとテストコードを作成する。defaultRollback = true で元通りになると油断していたら、オートインクリメントカラムのカウンタがロールバックされないため、ID に頼ったテストが失敗する。

データベースの初期データの作成には SQL を使うべきか、テスト済み Repository クラスを使うべきか。分からない。

テストケース内でのトランザクション

テストケース実行のたびにトランザクションを有効化、自動ロールバックする。

@TransactionConfiguration(defaultRollback = true)
@Transactional

またテストケースでは1メソッド内で exercise フェーズと verify フェーズを行うため、これらの処理を単に連続実行すると、同期されていないエンティティを検証することになる。そのためメソッド内で明示的に同期化する。

EntityManager em;
em.flush()
em.clear()

Entityクラスの継承

スーパークラスに次のようにアノテーションをつける。 つけなくてもお得意のデフォルト動作でなんとかしてほしいよおwwwww

InheritanceType の指定で、サブクラスとのテーブルの関係を決定できる。別テーブルとして用意して JOIN するか、1つのテーブルに統合するか、など。

@Inheritance(strategy = InheritanceType.JOINED)
+public class Item implements Serializable {

Spring Boot プロファイル指定

mvn spring-boot:run -Drun.jvmArguments="-Dspring.profiles.active=production"

spring-projects/spring-boot#1095

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment