前回
の続きでテーブル間の関連について見ていきます。今回はOneToMany。
1対多関連
1側となるFamily Entityを以下のように作成します。
public interface Family extends Entity { public String getName(); public void setName(String name); @OneToMany public Person[] getPeople(); }
アノテーションにて@OneToManyを指定することで1対多の関連を定義しています。オブジェクトとしては双方関連とします。
次に多側となる Person Entity を以下のように修正します。
public interface Person extends Entity { public String getName(); public void setName(String name); public int getAge(); public void setAge(int age); public Family getFamily(); public void setFamily(Family family); }
Familyに対する通常のアクセッサ-を追加します。
自動生成されるテーブル
上記インターフェース定義により以下のDDLが発行されることになります。
CREATE TABLE family ( id INTEGER GENERATED BY DEFAULT AS IDENTITY NOT NULL, name VARCHAR(255), PRIMARY KEY(id) ) CREATE TABLE person ( id INTEGER GENERATED BY DEFAULT AS IDENTITY NOT NULL, age INTEGER, name VARCHAR(255), familyID INTEGER, CONSTRAINT fk_person_familyid FOREIGN KEY (familyID) REFERENCES family(id), PRIMARY KEY(id) )
person テーブルには familyID というカラムが追加され、外部キーとして family テーブルの id が設定されています。
実行テストコード
実行確認用のテストコードを以下のように実装します。
@Test public void test() throws Exception { EntityManager em = new EntityManager("jdbc:hsqldb:hsql://localhost/test", "sa", ""); em.migrate(Person.class, Family.class); Family family = em.create(Family.class); family.setName("Yorke"); family.save(); Person p1 = em.create(Person.class); p1.setName("Thom"); p1.setAge(27); p1.setFamily(family); p1.save(); Person p2 = em.create(Person.class); p2.setName("Rachel"); p2.setAge(52); p2.setFamily(family); p2.save(); for(Person p : family.getPeople()) { System.out.println(p.getName()); }
実行結果は以下のようになります。
Thom Rachel
family.save() 後、2人の Person に family エンティテイを設定することで、family から設定した2人の Person が取得できていることが分かります。
その他の関連
1対1、多対多の関連についても前述と同じように @OneToOne アノテーション、 @ManyToMany アノテーションが用意されています。@ManyToMany では以下のように引数としてN対N連結用のテーブルとなるクラスを指定します。
@ManyToMany(PersonToPerson.class) public Person[] getPeople();