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:
今思えば意味の分からないことをやってますね。エンティティグループと所有非所有関連をまったく分かっていなかったのでしょう。いまでも完全に分かっているわけではないですが、ちょっとこれはわれながらひどいですね。あとで、機会があれば、まとめて見たいと思います。