2009年9月18日金曜日

JDOでListなどのコレクションを取得する時の注意点

Listのプロパティを取得しようとしたら以下のような例外が出た。
javax.jdo.JDODetachedFieldAccessException: You have just attempted to access field "tagNameList" yet this field was not detached when you detached the object. Either dont access this field, or detach it when detaching the object.
 at jp.co.tricell.sonicboom.Mutter.jdoGettagNameList(Mutter.java)
 at jp.co.tricell.sonicboom.Mutter.getTagKeys(Mutter.java:137)
 at jp.co.tricell.sonicboom.rpc.test.TestMutterUtils.testGetMutterOf(TestMutterUtils.java:69)
 at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
 at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:39)
 at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:25)
 at java.lang.reflect.Method.invoke(Method.java:597)
 at junit.framework.TestCase.runTest(TestCase.java:164)
 at junit.framework.TestCase.runBare(TestCase.java:130)
 at junit.framework.TestResult$1.protect(TestResult.java:106)
 at junit.framework.TestResult.runProtected(TestResult.java:124)
 at junit.framework.TestResult.run(TestResult.java:109)
 at junit.framework.TestCase.run(TestCase.java:120)
 at junit.framework.TestSuite.runTest(TestSuite.java:230)
 at junit.framework.TestSuite.run(TestSuite.java:225)
 at org.eclipse.jdt.internal.junit.runner.junit3.JUnit3TestReference.run(JUnit3TestReference.java:130)
 at org.eclipse.jdt.internal.junit.runner.TestExecution.run(TestExecution.java:38)
 at org.eclipse.jdt.internal.junit.runner.RemoteTestRunner.runTests(RemoteTestRunner.java:460)
 at org.eclipse.jdt.internal.junit.runner.RemoteTestRunner.runTests(RemoteTestRunner.java:673)
 at org.eclipse.jdt.internal.junit.runner.RemoteTestRunner.run(RemoteTestRunner.java:386)
 at org.eclipse.jdt.internal.junit.runner.RemoteTestRunner.main(RemoteTestRunner.java:196)
先日購入した「Google App Engine for Java[実践]クラウドシステム構築」P124に書いてった、
「JDOにはフェッチグループという概念があり、単一のエンティティ内でも一部のプロパティを遅延して取得できます。」
と言うことの意味がこれで分かった。

プリミティブ型、そのラッパークラス、String、Dateといった基本的な型がdefault fetch groupであり、エンティティのプロパティとして「遅延無く」取得できるものなのだ。

今回使用したListはこれらに含まれていないので、自分でdefault fetch groupの指定を追加しない限り、エンティティ取得当初はデータが含まれていないということなんだな。

ということで、例外が出たプロパティに以下のアノテーションを追加。
@Persistent(defaultFetchGroup = "true")
private List<String> tagNameList;
取得成功っと。