概要
Java と JDO 3 を使用して Appengine で動作するアプリケーションを使用しています。これらの引数 ( auto_now と auto_now_add ) は、Java で実装したいものと正確に一致しています。基本的に問題は次のとおりです。AppEngine の Python DateTimeProperty を Java JDO に変換する方法は?
制約
- アプリケーションを Python に変換することはできません。
- 2 つの Date プロパティを追加し、作成/更新が発生するたびにこれらの値を手動で設定することはできません。
- JDO/Appengine/データベースの作成者が API を作成したときに、このシナリオに対して念頭に置いていたことに対応するソリューションを探しています。
- 一般的なオプションを用意することをお勧めします。クラスに 4 つのエンティティ (C1、C2、C3、C4) があるとします。解決策は、4 つのエンティティすべてが拡張される基本クラス C0 を追加することであり、4 つのエンティティは拡張されません。彼らが「監査」されていることさえ知っています。
[更新]試してみました(単純なエンティティを使用)
@PersistenceCapable public class MyEntity {
@Persistent(valueStrategy = IdGeneratorStrategy.IDENTITY, primaryKey = "true")
private Long id;
@Persistent private String name;
...
1.@Persistent public void getLastUpdate() { return new Date(); }
回答で示唆されているように、データストアから値をロードしたり、無関係なフィールド (例: String name
) を変更したりしても、常に値が更新されるようです。
Java クラスにプロパティ (setter/getter) を設定し、そのプロパティを (フィールドではなく) 永続化することは簡単にできます。そのゲッター内で、データストアに入る値を制御したいものをコーディングできます。
次のハックを行わなかった場合、データストアに保存されている値を読み取ることができません [ハックでも :( ]:
@Persistent public Date getLastUpdate() { return new Date(); }
private Date prevUpdate;
public void setLastUpdate(Date lastUpdate) { this.prevUpdate = lastUpdate; }
public Date getPrevUpdate() { return prevUpdate; }
永続化操作が進行中であるか、コードがゲッターを呼び出しているかを区別する方法はありますか?
2.@Persistent(customValueStrategy = "auto_now_add") private Date lastUpdate;
に置き換えてモデリングauto_now_add
しました。しかし、他のフィールドを変更して を呼び出した回数に関係なく、最初の呼び出しで一度だけ入力されました。また、ドキュメントに記載されているように動作しないように見えることにも注意してください(または私の英語はさびています):org.datanucleus.store.valuegenerator.TimestampGenerator
Timestamp
java.util.Date
makePersistent
makePersistent
フィールドの値戦略を定義すると、デフォルトで、永続化時に常にそのフィールドの値が生成されることに注意してください。フィールドが null を格納でき、null の場合にのみ永続的に値を生成するようにしたい場合 (つまり、自分で値を割り当てていない場合)、拡張 "strategy-when-notnull" を false として追加できます。
3.preStore
使用するPersistenceManager.addInstanceLifecycleListener
期待どおりに動作しますが、基本クラスを使用して複数のエンティティで動作させることができました。
pm.addInstanceLifecycleListener(new StoreLifecycleListener() {
@Override public void preStore(InstanceLifecycleEvent event) {
MyEntity entity = (MyEntity)event.getPersistentInstance();
entity.setLastUpdate(new Date());
}
@Override public void postStore(InstanceLifecycleEvent event) {}
}, MyEntity.class);
4.implements StoreCallback
そしてpublic void jdoPreStore() { this.setLastUpdate(new Date()); }
期待どおりに動作しますが、基本クラスを使用して複数のエンティティで動作させることができました。
4 番目の制約を満たすには (ソリューション 3 または 4 を使用)
私が何をしても、次の構造を機能させることはできません:
public abstract class Dateable implements StoreCallback {
@Persistent private Date created;
@Persistent private Date lastUpdate;
public Dateable() { created = new Date(); }
public void jdoPreStore() { this.setLastUpdate(new Date()); }
// ... normal get/set properties for the above two
}
@PersistenceCapable public class MyEntity extends Dateable {
@Persistent(valueStrategy = IdGeneratorStrategy.IDENTITY, primaryKey = "true") private Long id;
@Persistent private String name;
エンハンサー実行時の問題:
public abstract class Dateable
:DataNucleus.MetaData クラス "[...].Dateable" を MetaData を持たないものとして登録しています。
public abstract class Dateable
上記のログを使用しますが、とにかくコードを実行します。
作成日は、データストアからデータを作成または読み取るたびに変更されます。@PersistenceCapable public abstract class Dateable
:DataNucleus.MetaData クラス "[...].MyEntity" は 1 つの主キー フィールドで指定されていますが、このクラスはデータストア ID を使用しており、アプリケーション ID である必要があります。