如何使用Java JDO 3在AppEngine DataStore中存储created / lastUpdate字段?

时间:2013-08-26 22:27:59

标签: java google-app-engine database-design google-cloud-datastore jdo

摘要

我使用Java和JDO 3在Appengine中有一个工作应用程序。 我发现这些参数(auto_now and auto_now_add)完全符合我想用Java实现的内容。所以基本上问题是:如何将AppEngine的Python DateTimeProperty转换为Java JDO?

约束

  1. 将我的应用程序转换为Python不是一种选择。
  2. 添加两个Date属性并在创建/更新发生时手动填充这些值不是一种选择。
  3. 我正在寻找一个解决方案,该解决方案与JDO / Appengine /数据库作者在创建API时对此方案的想法相对应。
  4. 最好有一个通用选项:说我在类中有4个实体:C1,C2,C3,C4,解决方案是添加一个基类C0,所有4个实体都将扩展,所以这4个实体甚至不知道他们被“审核”了。
  5. [更新]我尝试过(使用简单的实体)

    @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)并使属性可持久化(而不是字段)。在该getter中,您可以编写任何想要控制数据存储区中的值的代码。

    如果我没有执行以下hack,我无法读取存储在数据存储区中的值[既没有hack :(]:

    @Persistent public Date getLastUpdate() { return new Date(); }
    private Date prevUpdate;
    public void setLastUpdate(Date lastUpdate) { this.prevUpdate = lastUpdate; }
    public Date getPrevUpdate() { return prevUpdate; }
    

    有没有办法区分持久性操作是否正在进行或我的代码是否正在调用getter?

    2。 @Persistent(customValueStrategy = "auto_now_add") private Date lastUpdate;

    我在auto_now_addorg.datanucleus.store.valuegenerator.TimestampGenerator替换Timestamp之后对java.util.Date进行了建模。 但它只在第一次makePersistent调用时填充一次,无论我修改其他字段多少次并调用makePersistent。另请注意,它似乎不像documentation所说的那样(或者我的英语生锈了):

      

    请注意,通过为字段定义值策略,默认情况下,它始终会在持久性上为该字段生成值。如果该字段可以存储空值,并且您只希望它在为空时生成值(即您没有自己分配值),那么您可以将扩展名“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 StoreCallbackpublic 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个主键字段,但此类使用数据存储区标识,应该是应用程序标识。

1 个答案:

答案 0 :(得分:0)

JDO只提供Java类的持久性(及其字段/属性),因此不要看JDO的设计与它有什么关系。

您可以轻松地在java类上拥有属性(setter / getter)并使属性可持久化(而不是字段)。在该getter中,您可以编写任何想要控制数据存储区中的值的代码。或者您使用preStore侦听器,以便能够在持久性之前设置内容,以便将所需的值放入数据存储区。