« さらば PHS | メイン | 新宿南口 »

August 18, 2005

Hibernate の composite-element を使うときは equals() と hashCode() をオーバーライドする

という必要があるのに気づくまで、ちょっとハマったのでメモ。

Hibernate でコンポーネントのコレクションへのマッピングをするとき、つまりあるクラスのメンバに Set などのコレクションがあって、その中身が特定の値型のとき、composite-element を使います。そのとき、コレクションの中身になるクラスでは equals() と hashCode() をオーバーライドしないといけない、という話。

クラスが、

public class Group {
    private Integer id;
    private String groupName;
    private Set members = new HashSet(); // 中身は Person
    ....
}

public class Person {
    private String name;
    private Integer age;
    ....
}

みたいなとき、マッピングファイルは、

<hibernate-mapping>
    <class name="Group" table="group">
        <id name="id">
            <generator class="identity"/>
        </id>
        <property name="groupName" column="group_name"/>
        <set name="members" table="members">
            <key column="id"/>
            <composite-element class="Person">
                <property name="name"/>
                <property name="age"/>
            </composite-element>
        </set>
    </class>
</hibernate-mapping>

てな感じになるわけですが、ここで、Person に equals() と hashCode() を実装しておかないとですね、例えば Group に member を追加するときに、members テーブルに対して大量に insert と delete を発行してしまったり、わけわかんないことになります。まあよく考えてみれば確かにそうなるかも、というところですが、ドキュメントにも、

Note: if you define a Set of composite elements, it is very important to implement equals() and hashCode() correctly.

とか書いてあるので、注意が必要です。バッチリ見落としてましたよ。よく参考にしてるHibernate 入門記のエントリでも、

こいつは値型なので本来は hashCode() と equals(Object) をオーバーライドすべきですが,手抜きしてます.心より恥じる.
とあったのですが、これも見落としてました。いかんいかん。

投稿者 ryoji : August 18, 2005 10:47 AM

トラックバック

このエントリーのトラックバックURL:
http://ryoji.sakura.ne.jp/mt/mt-tb.cgi/148