軽量O/Rマッピングフレームワーク ActiveObjects その2

前回

blog1.mammb.com

の続きでテーブル間の関連について見ていきます。今回は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();