wiQuery - WicketとJQueryを統合するライブラリー その3

wiQueryの1.0.1がリリースされてます。

maven用のRepositoryが用意されたようなので今後はわざわざローカルにダウンロードして(ry
というようなことをする必要がなくなりました。

ちなみにpomには以下を追加すればOKです。

    <repositories>
        <!-- wiQuery用リポジトリー -->
        <repository>
            <id>wiquery repository</id>
            <name>wiQuery repository</name>
            <url>http://wiquery.googlecode.com/svn/repo/</url>
            <layout>default</layout>
        </repository>
    </repositories>
    <dependencies>
        <!-- wiQueryの依存関係追加 -->
        <dependency>
            <groupId>org.odlabs.wiquery</groupId>
            <artifactId>wiquery</artifactId>
            <version>1.0.1</version>
        </dependency>
        <!-- logger追加 -->
        <dependency>
            <groupId>org.slf4j</groupId>
            <artifactId>slf4j-log4j12</artifactId>
            <version>1.5.8</version>
        </dependency>
    </dependencies>

また、デフォルトではwiQueryの依存関係はwicket1.4.3なので、最新のWicketのバージョンにしたい人とLog4jやめてlogback使いたい人は下記のように設定すればOKです。

    <dependencies>
        <dependency>
            <groupId>org.odlabs.wiquery</groupId>
            <artifactId>wiquery</artifactId>
            <version>1.0.1</version>
            <exclusions>
                <exclusion>
                    <groupId>org.apache.wicket</groupId>
                    <artifactId>wicket</artifactId>
                </exclusion>
                 <exclusion>
                    <artifactId>log4j</artifactId>
                    <groupId>log4j</groupId>
                </exclusion>
            </exclusions>
        </dependency>
        <dependency>
            <groupId>org.apache.wicket</groupId>
            <artifactId>wicket</artifactId>
            <version>1.4.7</version>
        </dependency>
        <dependency>
            <groupId>ch.qos.logback</groupId>
            <artifactId>logback-classic</artifactId>
            <version>0.9.20</version>
        </dependency>
    </dependencies>

JPAのManyToOneにおける各ベンダーの違い

 JPA*1エンティティー間の多対一のリレーションを表現する@ManyToOneですが、こやつの振る舞いがベンダー間でちょっと違うようなのでメモしておきます。

振る舞いの違い

 どう違うのかというと、参照先のエンティティが物理的に存在しなければ取得時にEntityNotFoundExceptionをthrowするかどうか。
例えば下記のテーブルとデータがあるとします。
EMPLOYEEテーブル

EMPLOYEE_ID NAME
1 Hoge
2 Foo
3 Bar

EXPENSEテーブル

EXPENSE_ID AMOUNT EMPLOYEE_ID
1 130 1
2 930 2
3 2,340 4

EXPENSEテーブルのEMPLOYEE_IDとEMPLOYEEテーブルのEMPLOYEE_IDとの間には論理的な参照が存在します(物理的な制約(参照整合性制約)があるわけではありません)。また、EXPENSEテーブルの3行目のデータは存在しないEMPLOYEEのIDを参照してしまっているゴミデータです。

この時の各テーブルに対するエンティティは下記になります。

Employeeエンティティ

@Entity
@Table(name = "EMPLOYEE")
public class Employee implements Serializable {
    private static final long serialVersionUID = 1L;
    @Id
    @Column(name = "EMPLOYEE_ID")
    private Integer employeeId;
    @Column(name = "ZIP")
    private String zip;
    @OneToMany(cascade = CascadeType.ALL, mappedBy = "employee")
    private List<Expense> expenseList;
    //アクセサは省略

Expenseエンティティ

@Entity
@Table(name = "EXPENSE")
public class Expense implements Serializable {
    private static final long serialVersionUID = 1L;
    @Id
    @Column(name = "EXPENSE_ID")
    private Integer expenseId;
    @Column(name = "AMOUNT")
    private BigDecimal amount;
    @JoinColumn(name="EMPLOYEE_ID",referencedColumnName="EMPLOYEE_ID")
    @ManyToOne
    private Employee employee;

    //アクセサは省略

 この時EXPENSE_IDが3(ゴミデータ)を取得しようとした時にベンダー間で振る舞いが変わってきます。
調べたベンダーとバージョンは以下です。

  • OpenJPA 1.2.2(JPA1.0実装)
  • Hibernate EntityManager 3.2.0-GA(JPA1.0実装)
  • Hibernate EntityManager 3.5.0-FINAL(JPA2.0実装)
  • OpenJPA 2.0.0Beta3(JPA2.0実装)
  • EclipseLink2.0.0(JPA2.0実装)

んで、実際どうなのか

  • EntityNotFoundExceptionをthrowする
    • Hibernate EntityManager 3.2.0-GA(JPA1.0実装)
    • Hibernate EntityManager 3.5.0-FINAL(JPA2.0実装)
  • EntityNotFoundExceptionをthrowせずに取得時(getEmployeeが呼び出された時)にnullを返す
    • OpenJPA 1.2.2(JPA1.0実装)
    • OpenJPA 2.0.0Beta3(JPA2.0実装)
    • EclipseLink2.0.0(JPA2.0実装)

 この振る舞いの違いって結構デカいと思うのですがどうでしょうか??「ちょっくらJPAの実装変えてみようZE!」的なノリでやった場合に予期せぬ場所で例外が吹っ飛ぶことになります。テーブルに対して物理的に参照整合性制約を付けていればバッチ等でデータが流された場合も整合性は保たれるでしょうが、そもそも参照整合性制約がかけれない状況だってあるわけで。というか調べた限りHibernateだけ独自っぽいです。自分はHibernateJPA実装歴が長かったのでOpenJPAやEclipseLinkを試すまで例外が吹っ飛ぶのがJPAの仕様だと勘違いしてました。(そういや初期のJPA-Hibernate実装はfindメソッドで存在しない場合はEntityNotFoundExceptionをthrowしてました。今はちゃんとJPAの仕様どおりnullを返すようです。こちらも自分はずっとそれがJPAの仕様だと勘違いしてました。)
 じゃあHibernateでOpenJPAやEclipseLinkのような振る舞いにすることはできないのかというともちろんできます。@ManyToOneのカラムに@NotFoundアノテーションを付けます。

    @NotFound(action=NotFoundAction.IGNORE)    
    @JoinColumn(name="EMPLOYEE_ID",referencedColumnName="EMPLOYEE_ID")
    @ManyToOne
    private Employee employee;

 しかしここでも問題があります。@NotFoundアノテーションHibernate独自のアノテーションです。つまりベンダー依存になっちゃうんですよね〜。これじゃあせっかくの標準仕様が台無しです><。persistence.xmlへの記述でなんとか回避出来ないか調べてみたんですが今のところ見つけられず・・・。個人的には例外が吹っ飛んで欲しいのでOpenJPAとEclipseLinkがHibernateに合わせて(というかJPAの標準仕様にして)、例外が吹っ飛んで欲しくない場合は@ManyToOneのオプションで制御とかやって欲しい感じです。

 ちなみにOpenJPAやEclipseLinkで参照先が存在しないエンティティをそもそも取得したくない場合は下記のようにします。

    @ManyToOne(optional=false)

ただし、これだとfindメソッドでPK検索した場合も取得できないという仕様みたいです・・・。う〜ん、それもどうなの?って感じですねぇ〜。

*1:1.0、2.0の両方

TDD Boot Camp北陸 - 感想とか

感想と、参加した上での今後の目標とか書いていこうかなと思います。

旅立ち

 実は新幹線に乗り遅れそうでしたw。まじであせりましたが、なんとか乗れてよかった。途中米原からの特急に乗ってからは一緒に行った友人とPC立ち上げて「あーだこーだ」言いながらペアプロしてました。ぶっちゃけ周りからはかなりイタイ感じでみられていたんじゃないかとw。

id:t-wadaさんのお話

 ジョジョスティール・ボール・ランTDDに関するお話。以前の資料は拝見させていただいてのですが、やっぱり直接聞くのは全然違いますね、三本柱の例えが非常に印象的でした。あとassertファーストに関してはどこかの資料か本で読んでたはずが忘れていました・・・反省してちゃんと実践します。

TDD & ペアプロ

 お題に対してテストファーストペアプロでコーディングするという形式。前後半でペアを替えてやったのですが、やっぱりペアプロは楽しいですね〜。ペアになった人の意見をダイレクトに聞けるのが何より良いです。仕事でもずっとペアプロやってますがいつもと違う方々とペアプロできて非常に勉強になりました。自分とペアを組んだ方も楽しいと思っていただけていたら良いのですが・・・、そのあたりの感想を聞くのを忘れていた事を非常に後悔してます。

コードレビュー

 みんなが書いたソースのコードレビューを行ったのですが、これがまた凄く勉強になりました。今回はいろいろな言語でそれぞれTDD&ペアプロしていたので各言語でのテストの書き方とか知ることができて良かったです。以下ちょっとした感想。

  • NUnitのパラメータライズドテストの書き方がシンプルでいい。
  • RSpecはやっぱり直感的でいいしレポーティング機能がまた素晴らしい。
  • PHPはLLの中ではJavaと構文が結構似てることもあって(自分も以前使ってたこともあり)わかりやすかった。
  • Pythonのドキュメント機能が格好良かった。
  • C#いい!
  • というかJavaが一番もっさり感があった(他人の芝は〜的感覚のせい??)

夕食、その後

 鍋が美味しかったです。温泉もよかった〜。id:t-wadaさんにテストの事、設計の事、DDDの事、Mockの事とか日頃自分が疑問に思ってることを聞けて凄く勉強になりました。丁寧にお答え頂きほんとにありごうとございます。あとtwitterやってないと人として認められない的なことを大阪の人に言われたのでさっそくtwitterアカウント取得しときましたw。

2日目の午前中

 レガシーコード(テストの無いコード)に対するテストの書き方をid:t-wadaさんとid:katzchangさんがペアプロしながらライブコーディングする形式。レガシーコードに対して他人がテストを書く所を生で見れたのが一番よかったです。やはり他の人の考え方とかアプローチの仕方とかは勉強になりますね。

2日目の午後

 午前をふまえた上で、各言語に分かれてレガシーコードに対してテストを書いていくという形式。Javaのお題になったソースコードはそもそもテストを書く事に対して敷居の高いGUIのアプリケーションだったので中途半端な所で時間が来てしまい個人的に不完全燃焼感がのこったのですが、1つのソース(課題)に対して複数人が取り組みながらコーディングしていく形式は面白かったです。ここでも他の人の考えを色々聞けて凄く勉強になりました。

帰り

 帰りの新幹線でもまた友人とペアプロしてましたw。まわりから(ry

全体的な感想

 凄く勉強になりました。特にJava以外の言語で同じ課題に対するテストの書き方を見れたのがよかった〜。いろんな宗教戦争(OSとかキーボード配列とかPCとかテスト用ライブラリとか言語とか)は楽しかったですw。あと、ほとんどの人が複数言語を当たり前のように扱えててSUGEE!って思いました。自分まだまだヘボいなぁというのが再確認できて勉強の意欲が上がってよかったです。

今回参加した結果今後こういうことやっていこうとかいうの

 「勉強になった」「楽しかった」だけでは無く今後どうやっていくかってのもこういう勉強会に参加した後は凄く大事だと思うのでそのへんつらつら書いていこうかなと

  • JUnitにおけるParameterizedテスト機能の導入検討(この機能が提供する高価の本質も含め、どういう状況で一番効果があるか等の調査)
  • assertファーストの実践
  • DDDを参考にしたサンプルソースを見た上でのDDDの本質の探求
  • Hudsonのプラグインを作ってみる
  • twitterのアカウントを作る(作成済み)
  • Mockを使ったテストに関して自分の中でもう1度ちゃんと整理する(エントリー書こうかなぁ)
  • Emacsをもっと使いこなす

最後に

 主催者の方々、参加された方々ほんとにお疲れさまでした&ありがとうございました!

Twitterはじめますた

とりあえずはじめてみますた。
使い方がまったくわからないので少しずつ勉強していきます。
IDははてなと同じのが使用済だったのでちょっと変えておきました。

IDはt_hysshです。

とりあえずよくつぶやくと聞いたケント・ベックはフォローしときました。

wiQuery - WicketとJQueryを統合するライブラリー その2

 本家WicketのMLでwiQueryを使った新しいデモサイトが話題になっているっぽいのでリンクだけ貼っておきます。

wiQuery恐ろしい子!

Grid demosは驚愕モノです・・・・