GAEでunownedな関連を定義する方法
Google App Engineでは、関連の実装として、キーの親子関係で実現するownedな関連と、キーの親子関係ではなく、単に相手のキーを持つだけのunownedな関連があります。
unownedな関連は、RDBMSにおけるFKを持っているようなものだと思うとイメージしやすいと思います。
例えば、次の例では、FooがBarをunownedな関連先として定義しています。
@PersistenceCapable(identityType = IdentityType.APPLICATION, detachable = "true")
public class Foo {@PrimaryKey
@Persistent(valueStrategy = IdGeneratorStrategy.IDENTITY)
@Extension(vendorName = "datanucleus", key = "gae.encoded-pk", value = "true")
private String key;@Persistent
private String barKey;public String getKey() {
return key;
}public void setKey(String key) {
this.key = key;
}public String getBarKey() {
return barKey;
}public void setBarKey(String barKey) {
this.barKey = barKey;
}
}
@PersistenceCapable(identityType = IdentityType.APPLICATION, detachable = "true")
public class Bar {@PrimaryKey
@Persistent(valueStrategy = IdGeneratorStrategy.IDENTITY)
@Extension(vendorName = "datanucleus", key = "gae.encoded-pk", value = "true")
private String key;public String getKey() {
return key;
}public void setKey(String key) {
this.key = key;
}
}
これが基本。でも、FooからBarを取得しようとしたときに、キーしかもっていないので、何かと不便です。特に、JSPでFooのインスタンスからBarを取得しようとすると路頭に迷います。
unownedな関連を実現するときは、次のようにするのがお勧めです。ポイントは、barKeyプロパティではなく、仮想的なbarプロパティを使うところ。これで、関連を自然な形で扱うことができます。
@PersistenceCapable(identityType = IdentityType.APPLICATION, detachable = "true")
public class Foo {@PrimaryKey
@Persistent(valueStrategy = IdGeneratorStrategy.IDENTITY)
@Extension(vendorName = "datanucleus", key = "gae.encoded-pk", value = "true")
private String key;@Persistent
private String barKey;public String getKey() {
return key;
}public void setKey(String key) {
this.key = key;
}public Bar getBar() {
if (barKey == null) {
return null;
}
return JDOHelper.getPersistenceManager(this).getObjectById(Bar.class, barKey);
}public void setBar(Bar bar) {
if (bar == null) {
barKey = null;
}
barKey = bar.getKey();
}
}
JDOHelper.getPersistenceManager(this)でPersistenceManagerが取得できるのは、モデルがpersistentな状態(detachedな状態になったらだめ)のときだけです。
persistence.xmlでdetachOnCommitがtrueになっているとcommitされたときにdetached状態になってしまうので、falseにしておきましょう。
また、リクエストを処理している間、モデルがpersistentな状態でいられるようにFilterでPersistenceManagerを管理するといいでしょう。Slim3はそうなってます。
これでJSPでは、${foo.bar.key}のような感じで簡単にアクセスできます。