Java:JDO:List<String> データの永続化問題

120 views
Skip to first unread message

のらぐらま

unread,
Oct 5, 2009, 8:25:32 PM10/5/09
to Google-App-Engine-Japan
下のコードですが、想定する動作を行いません。
retrieveを明示的にいれてあげないと、
キャッシュを読み込まないせいでエラーになるみたいです。
キャッシュ管理って、基本自動だと思ってたのですが、
錯覚なんでしょうか?
なんか予想の斜め上いく動作です。

package xxx;
import java.util.List;

import javax.jdo.annotations.IdGeneratorStrategy;
import javax.jdo.annotations.IdentityType;
import javax.jdo.annotations.PersistenceCapable;
import javax.jdo.annotations.Persistent;
import javax.jdo.annotations.PrimaryKey;

@PersistenceCapable(identityType = IdentityType.APPLICATION)
public class Month {
@SuppressWarnings("unused")
@PrimaryKey
@Persistent(valueStrategy = IdGeneratorStrategy.IDENTITY)
private Long id;
public Long getId(){
return id;
}
public Month(){
}
@Persistent
List<String> names;
}

package xxx;
import java.util.ArrayList;
import javax.jdo.PersistenceManager;
import javax.jdo.Query;

public class MonthTest extends LocalDatastoreTestCase {
public void testSetup(){
assertNull(null);
}
public void testSaveAndLoad(){
PersistenceManager pm = PMF.getPersistenceManager();
Month m = new Month();
Long x ;
m.names = new ArrayList<String>();
m.names.add("Jan");
m.names.add("Feb");
pm.makePersistent(m);
x = m.getId();
System.out.println(x));
assertEquals(2,m.names.size());
pm.close();

pm = PMF.getPersistenceManager(); // reOpen
Query q = pm.newQuery(Month.class);
Month b =(Month)pm.getObjectById(Month.class,x);
//pm.retrieve(b); // これをコメントアウトするとエラー
assertEquals(new Long(1),b.getId());
assertEquals(2,b.names.size());
pm.close();
}
}

渡健太

unread,
Oct 5, 2009, 8:47:51 PM10/5/09
to google-app-...@googlegroups.com
渡といいます。初めまして。

MonthクラスのList<String> nameにgetter
public List<String> getName() {
return name;
}
を追加して、getter経由でアクセスしてみてください。

http://code.google.com/intl/ja/appengine/docs/java/datastore/dataclasses.html
>ヒント: すべての永続フィールドを private または protected(あるいは package protected)にし、
>アクセサ メソッドによるパブリック アクセスのみを提供します。
>他のクラスから永続フィールドに直接アクセスすると、JDO のクラス拡張をバイパスしてしまう場合があります。
>他のクラスを @PersistenceAware にする方法もあります。
>詳しくは、DataNucleus のドキュメントをご覧ください。
です。

2009年10月6日9:25 のらぐらま <ich...@ff.iij4u.or.jp>:

のらぐらま

unread,
Oct 6, 2009, 10:36:22 PM10/6/09
to Google-App-Engine-Japan
On 10月6日, 午前9:47, 渡健太 <kenta.wat...@gmail.com> wrote:
> 渡といいます。初めまして。
>
> MonthクラスのList<String> nameにgetter
> public List<String> getName() {
> return name;}
>
> を追加して、getter経由でアクセスしてみてください。
>
> http://code.google.com/intl/ja/appengine/docs/java/datastore/dataclas...
> >ヒント: すべての永続フィールドを private または protected(あるいは package protected)にし、
> >アクセサ メソッドによるパブリック アクセスのみを提供します。
> >他のクラスから永続フィールドに直接アクセスすると、JDO のクラス拡張をバイパスしてしまう場合があります。
> >他のクラスを @PersistenceAware にする方法もあります。
> >詳しくは、DataNucleus のドキュメントをご覧ください。
> です。
もともとアクセサ経由のでセーブできなくて、
ちょっと説明用とテスト用に切り出して、こちらあげてみたのです。
この例だと動くようになるけど、本番のソースコードのほうが通りませんね。
うーん、なんか見落としがりそうです。
どうもありがとう。
> > }- 引用テキストを表示しない -
>
> - 引用テキストを表示 -

のらぐらま

unread,
Oct 9, 2009, 7:25:26 PM10/9/09
to Google-App-Engine-Japan
やっとわかったというかなんというか。
@PersiceCapable(Identify..........................)
public class Test
@Persistent
User user;
@Persistent
List<String> data;

void testSave (User user,String x) {
PersistenceManager pm = PMF.getPersistenceManager();
Query q = pm.newQuery(Test.class);
q.setFilter("user == userParam");
q.declareVariables("String userParam");
List<Test> testList = q.execute(user);
Test test = null;
if ( testList.size() == 0 ) {
test = new Test();
test.data = new ArrayList<String>();
pm.makePersistent(test);
} else {
test = testList.get(0);
}
test.data.add(string);
pm.close();
}
こういうコード書いてたのですが、この書き方がダメだったみたいです。
makePersistentしても、ArrayListが適合しないせいで、
test.data.addこれの実行がデータベースに反映されなかったみたい。
test.data.addしてからmakePersistentしないと、データが保存されない。
つまりif文で分岐したら、そのまま分けて書かないとダメなんですね。
ということは、makePersistantは最初のオブジェクトだともう一度クローズして
読み直すか、dettachするしかないのかな。
上のコードは、該当部分から抜き出してデフォルメしてるので、
そのまま動く人もいるかもしれません。ちょっと検はしてないです。
> > - 引用テキストを表示 -- 引用テキストを表示しない -
>
> - 引用テキストを表示 -

WdWeaver

unread,
Oct 13, 2009, 2:50:03 AM10/13/09
to Google-App-Engine-Japan
渡です。

makePersistent後のコレクションへの変更が保存されないのは
datanucleus-appengineのバグです。

どうしてもこのコードでということであれば
JDOHelper.makeDirty(entity)
で変更は保存されます。

※ただ、これもトランザクションを利用する場合は動作しないようです。
Reply all
Reply to author
Forward
0 new messages