Keyとかエンティティグループとか
開発サーバでお試し勉強中 slim3itのBlogアプリをきっかけにべたのJDOを試してみています。
キーの型には4種類あるらしい(Keyオブジェクト、それをエンコードした文字列型、Long、エンコードしない文字列型)
何をやりたかったかというと、Shohinエンティティは親としてCategoryを参照していて、まずCategoryのキーはStringでエンコードしない文字列として宣言し、アプリケーション側でセットしてみてデータストアに登録してみる。これは別にできる。今回は試すのが目的なので、実際にキーはこのケースではどれがベストなのかとかはまったく考えずにやっています。ただキーの文字列が"100"とか数値の文字列だとmakePersistentでエラーが出た。
以下のコードでは、CategoryのID(エンコードしない文字列型で登録したもの)をキーにデータストアを検索し、結果のCategoryをShohinのcategoryフィールドにセットしてその商品はそのカテゴリーだよということ実現してみたかった。
のだが・・・・・
@PersistenceCapable(identityType = IdentityType.APPLICATION, detachable = "true") @Version(strategy = VersionStrategy.VERSION_NUMBER, column = "version") public class Category implements Serializable { private static final long serialVersionUID = 1L; //エンコードされない文字列。アプリで設定する @PrimaryKey private String id; @Persistent private String categoryname; @Persistent private Long version = 1L; public Long getVersion() { return version; } public String getId() { return id; } public void setId(String id) { this.id = id; } public String getCategoryname() { return categoryname; } public void setCategoryname(String categoryname) { this.categoryname = categoryname; } }
@PersistenceCapable(identityType = IdentityType.APPLICATION, detachable = "true") @Version(strategy = VersionStrategy.VERSION_NUMBER, column = "version") public class Shohin implements Serializable { private static final long serialVersionUID = 1L; @PrimaryKey @Persistent(valueStrategy = IdGeneratorStrategy.IDENTITY) @Extension(vendorName = "datanucleus", key = "gae.encoded-pk", value = "true") private String key; @Persistent private Category category; @Persistent private Long version = 1L; public Long getVersion() { return version; } @Persistent private String shohinname; public String getKey() { return key; } public void setKey(String key) { this.key = key; } public String getShohinname() { return shohinname; } public void setShohinname(String shohinname) { this.shohinname = shohinname; } public Category getCategory() { return category; } public void setCategory(Category category) { this.category = category; } }
@SuppressWarnings("serial") public class InsertGAEServlet extends HttpServlet { public void doPost(HttpServletRequest req, HttpServletResponse resp) throws IOException { Shohin sho = new Shohin(); String id = req.getParameter("category.id"); PersistenceManager pm = PMF.get().getPersistenceManager(); Transaction tx = pm.currentTransaction(); tx.begin(); try { Category ca = pm.getObjectById(Category.class, id); sho.setCategory(ca); sho.setShohinname(req.getParameter("shohinname")); pm.makePersistent(sho); tx.commit(); }catch(Exception e){ System.out.println(e.toString()); } finally { pm.close(); } resp.sendRedirect("/result.jsp"); } }
これは、落ちた
java.lang.IllegalArgumentException: can't operate on multiple entity groups in a single transaction. found both com.google.appengine.api.datastore.dev.LocalDatastoreService$Profile$EntityGroup@1f250e8 and com.google.appengine.api.datastore.dev.LocalDatastoreService$Profile$EntityGroup@19de9c9
親としてセットしてあげたことで、この二つはエンティティグループになるわけではないのか?わからん。頭が悪い。
Categoryをデータストアから持ってくるんじゃなくて、newしてあげてキーをセットして、ShohinをmakePersistentしたらちゃんと登録できた。保存しちゃったら関係を作ることはできない?サイトにもそんなようなことが書いてあった。詳しいことは分かってないのですが、これはできて、これはできないというのはわかった。
追記:2009/09/09:
今思えば意味の分からないことをやってますね。エンティティグループと所有非所有関連をまったく分かっていなかったのでしょう。いまでも完全に分かっているわけではないですが、ちょっとこれはわれながらひどいですね。あとで、機会があれば、まとめて見たいと思います。