5 高度な関連

この章では、テーブル間関連性をどのようにXMLファイルに記述するか、そうすることでどのようなJavaファイルが生成され、プログラムの中でどのように扱われるのか、そのようなことに関するいろいろなサンプルが登場してきます。多対多の関係をRDBSで表現するために、Hibernateが自動的にジョインテーブルを生成しますが、エンティティテーブルのデータが削除された時も、このジョインテーブルの関連するデータまで削除してくれるという親切さには驚きました。不整合データやゴミデータが発生しないようにするための仕組み、という観点からも調査していきたいなと思っています。
本章の最後に、再帰的な関連を表現する方法が少しだけ掲載されています。これをもとに、一つのテーブルに保持されているツリー構造のデータを上手くHibernateで扱えるかをいろいろと試してみました。の扱い方が理解しきれていませんが、何回か書いていく内に慣れていくでしょう。

<hibernate-mapping>
  <class name="com.oreilly.hh.Tree" table="TREE">
    <meta attribute="class-description">
      Represents an album in the music database, an organized list of tracks.
      @author Jim Elliott (with help from Hibernate)
    </meta>

    <id name="id" type="int" column="TREE_ID">
      <meta attribute="scope-set">protected</meta>
      <generator class="native"/>
    </id>

    <property name="name" type="string">
      <meta attribute="use-in-tostring">true</meta>
      <column name="NAME" not-null="true" index="TREE_NAME"/>
    </property>
	
    <many-to-one name="parent" class="com.oreilly.hh.Tree">
      <meta attribute="use-in-tostring">true</meta>
    </many-to-one>
	
    <set name="children">
      <key><column name="PARENT_ID"/></key>
      <one-to-many class="com.oreilly.hh.Tree"/>
    </set>

  </class>
</hibernate-mapping>
public class Tree implements Serializable {

    /** identifier field */
    private Integer id;

    /** nullable persistent field */
    private String name;

    /** nullable persistent field */
    private com.oreilly.hh.Tree parent;

    /** persistent field */
    private Set children;

    /** full constructor */
    public Tree(String name, com.oreilly.hh.Tree parent, Set children) {
        this.name = name;
        this.parent = parent;
        this.children = children;
    }

    /** default constructor */
    public Tree() {
    }

    // 省略
}
+-----------+--------------+------+-----+---------+----------------+
| Field     | Type         | Null | Key | Default | Extra          |
+-----------+--------------+------+-----+---------+----------------+
| TREE_ID   | int(11)      | NO   | PRI | NULL    | auto_increment | 
| NAME      | varchar(255) | NO   | MUL | NULL    |                | 
| parent    | int(11)      | YES  | MUL | NULL    |                | 
| PARENT_ID | int(11)      | YES  | MUL | NULL    |                | 
+-----------+--------------+------+-----+---------+----------------+

親子関係の表現がイマイチですが、上記のようなエンティティを操作するプログラムを書いてみると、確かに親をロードしたら、それと同時に子のSetもロードされていたり、子をロードしたら親にもアクセスできたり、親の情報を変更して自身のオブジェクトをsession.save()に渡したら、親の情報がしっかりと保存されたりして、O/Rマッピングの面白さを体感することができました。どのようなSQL文が流れているのかという点までは調査できませんでしたが、本章で紹介されていた遅延処理を上手いこと施してやれば、より効率的な仕組みを作ることができるのではないかと思いました。