の続きです。今回は Polymorphic について見ていきます。
多様性関連のマッピング
Person が請求明細(BillingDetails)を1つ持つことを考えます。この請求明細は、クレジットカード(CreditCard)か銀行口座(BankAccount)の何れかであるとします。このような多様性を表すEntityクラスとして以下の3つのクラスを定義します。
@Polymorphic public interface BillingDetails extends Entity { public int getNumber(); public void setNumber(int number); } public interface CreditCard extends BillingDetails { public String getExpYear(); public void setExpYear(String expYear); } public interface BankAccount extends BillingDetails { public String getBankName(); public void setBankName(String bankName); }
請求明細(BillingDetails)には@Polymorphicアノテーションを指定して、ActiveObjectsに多様性構造であることを伝えます。
では請求明細を持つ Person エンティテイを以下のように修正しましょう。
public interface Person extends Entity { public String getName(); public void setName(String name); public int getAge(); public void setAge(int age); public BillingDetails getBillingDetails(); public void setBillingDetails(BillingDetails bill); }
EntityManagerの設定
多様性を扱うエンティティは以下のようにEntityManagerにタイプマッパを指定します。
em.setPolymorphicTypeMapper( new DefaultPolymorphicTypeMapper(BankAccount.class, CreditCard.class));
これにより、BankAccount クラスと CreditCard クラスのType定義文字列として、bankAccountと creditCard という文字が使われるようになります。
自動生成されるテーブル
上記インターフェース定義により以下のDDLが発行されます。これを見るとわかる通り、具象クラス毎に1つのテーブルが作成されます。
CREATE TABLE person ( id INTEGER GENERATED BY DEFAULT AS IDENTITY NOT NULL, age INTEGER, billingDetailsID INTEGER, billingDetailsType VARCHAR(127), name VARCHAR(255), PRIMARY KEY(id) ) CREATE TABLE bankAccount ( id INTEGER GENERATED BY DEFAULT AS IDENTITY NOT NULL, bankName VARCHAR(255), number INTEGER, PRIMARY KEY(id) ) CREATE TABLE creditCard ( id INTEGER GENERATED BY DEFAULT AS IDENTITY NOT NULL, expYear VARCHAR(255), number INTEGER, PRIMARY KEY(id) )
person テーブルの billingDetailsType に先程説明したType定義文字列が入ることになります。
実行テストコード
実行確認用のテストコードを以下のように実装します。
@Test public void test() throws Exception { EntityManager em = new EntityManager("jdbc:hsqldb:hsql://localhost/test", "sa", ""); em.setPolymorphicTypeMapper( new DefaultPolymorphicTypeMapper(BankAccount.class, CreditCard.class)); em.migrate(Person.class, BankAccount.class, CreditCard.class); BankAccount bankAccount = em.create(BankAccount.class); bankAccount.setBankName("Tokyo"); bankAccount.setNumber(999); bankAccount.save(); CreditCard creditCard = em.create(CreditCard.class); creditCard.setNumber(666); creditCard.setExpYear("2010"); creditCard.save(); Person p1 = em.create(Person.class); p1.setName("Thom"); p1.setAge(27); p1.setBillingDetails(bankAccount); p1.save(); Person p2 = em.create(Person.class); p2.setName("Rachel"); p2.setAge(27); p2.setBillingDetails(creditCard); p2.save(); for(Person p : em.find(Person.class)) { System.out.println(p.getBillingDetails()); }
実行結果は以下のようになります。
bankAccount {id = 0} creditCard {id = 0}
Person に各具象クラスの内容が設定されていることが確認できます。