2012年11月15日木曜日

[AppEngine] jdoconfig のパラメータ

AppEngine の Eclipse プラグインでプロジェクトを作成すると、JDO 用の設定ファイルである jdoconfig.xml が作成される。
その中に、

<property name="javax.jdo.option.NontransactionalRead" value="true"/>
<property name="javax.jdo.option.NontransactionalWrite" value="true"/>
<property name="javax.jdo.option.RetainValues" value="false"/>
<property name="datanucleus.appengine.autoCreateDatastoreTxns" 
             value="true"/>

というパラメータがある。 JDO のドキュメント によると意味は以下の通り。

パラメータ意味
NontransactionalReadWhether to allow nontransactional reads
NontransactionalWriteWhether to allow nontransactional writes
RetainValuesWhether to suppress the clearing of values from persistent instances on transaction completion

autoCreateDatastoreTxns は JDO で規定されているパラメータではなく App Engine 固有の設定なので、 App Engine のトランザクションの説明 に記載されている。
false にすると JDO 的にトランザクションを有効にしても データストアのトランザクションは起動しないらしい。

実際に試してみよう。


NontransactionalRead/Write


このパラメータではトランザクション外でのデータの Read/Write の可否を設定する。

   <property name="javax.jdo.option.NontransactionalRead" value="true"/>
   <property name="javax.jdo.option.NontransactionalWrite" value="true"/>

デフォルトの Read/Write=true の状態では、トランザクションが開始されていても、開始されていない場合でもRead/Writeを行うことができる。

<property name="javax.jdo.option.NontransactionalRead" value="true"/>
<property name="javax.jdo.option.NontransactionalWrite" value="false"/>

NontransactionalWrite を false にした場合、トランザクションが開始されている場合には書き込みできるが、トランザクションを開始せずに書き込みをすると、

Uncaught exception from servlet
org.datanucleus.jdo.exceptions.TransactionNotWritableException: 
  Impossible to perform operation since it either requires an active 
  transaction or 'NontransactionalRead' enabled. You have neither of these.

というエラーが発生する。今回はエンティティ作成操作を実施したので、 PersistenceManager#makePersistent を実行時にエラーが発生している。
Read操作だけならトランザクションの有無にかかわらずエラーは発生しない。

<property name="javax.jdo.option.NontransactionalRead" value="false"/>
<property name="javax.jdo.option.NontransactionalWrite" value="true"/>

NontransactionalRead を false にした場合、トランザクションが開始されている場合には読み込みはできるが、トランザクションを開始せずに読み込みをすると

org.datanucleus.jdo.exceptions.TransactionNotReadableException:
  Impossible to perform operation since it either requires an active
  transaction or 'NontransactionalRead' enabled. You have neither of these.

というエラーが発生した。JDOQuery#execute でクエリーを実行する際に発生している。
Write 操作ではエラーは発生しない。


javax.jdo.option.RetainValues


この値を false にしたら コミット後に 永続化オブジェクトの値がクリアされるとのこと。
RetainValues を false にセットしてこんなコードで試してみる。

  PersistenceManager pm = PMF.get().getPersistenceManager();
  Transaction tx = null;
  try {
    tx = pm.currentTransaction();
    tx.begin();
    MyData data = new MyData();
    data.setName("one");
    pm.makePersistent(data);
    tx.commit();
    resp.getWriter().println("id: " + data.getId().toString());
    resp.getWriter().println("name: " + data.getName());
  } finally {
    if ( tx != null && tx.isActive() ) {
      tx.rollback();
    }
    if ( pm !=null && ! pm.isClosed()) {
      pm.close();
    };
  }

--------------------
id: 31002
name: one

クリアされていなかった。こういうことじゃないのかな? 不明。


autoCreateDatastoreTxns


JDO のトランザクションを開始したときにデータストアのトランザクションを連動させるか否かを設定する。このパラメータを false に設定すると、

Transaction tx = pm.currentTransaction();
tx.begin();
for (int i=0; i<10; i++) {
    MyData data = new MyData();
    data.setName("one");
    pm.makePersistent(data);
}
tx.commit();

こんな風に1トランザクション中でいくつでもエンティティが作成できる。
ただし、

Transaction tx = pm.currentTransaction();
tx.begin();
for (int i=0; i<10; i++) {
    MyData data = new MyData();
    data.setName("one");
    pm.makePersistent(data);
}
tx.rollback();

とロールバックしてもロールバックされない。
要はコード上トランザクションを使っていても全くトランザクションが効いていない状態になっている。

もともと RDBMS で動作していた(複数のレコードをトランザクション内で操作している) JDO アプリを、無理やり App Engine で動かすためのパラメータとのことなので、通常はこれを false にすることはない。

0 件のコメント:

コメントを投稿