0

抽象的

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

约束

  1. 将我的应用程序转换为 Python 不是一种选择。
  2. 添加两个 Date 属性并在创建/更新发生时手动填充这些值不是一种选择。
  3. 我正在寻找一种解决方案,它与 JDO/Appengine/Database 作者在创建 API 时针对此场景的想法相对应。
  4. 最好有一个通用选项:假设我在类中有 4 个实体:C1、C2、C3、C4,解决方案是添加一个基类 C0,所有 4 个实体都会扩展,所以 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),并使该属性可持久化(而不是字段)。在该 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_add后建模。但它只在第一次调用时填充一次,无论我修改了多少次其他字段并调用了. 另请注意,它的行为似乎不像文档所说的那样(或者我的英语生疏了):org.datanucleus.store.valuegenerator.TimestampGeneratorTimestampjava.util.DatemakePersistentmakePersistent

请注意,通过为字段定义值策略,默认情况下,它将始终在持久化时为该字段生成一个值。如果该字段可以存储空值,并且您只希望它在为空时生成持久值(即您自己没有分配值),那么您可以将扩展名“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()); }

按预期工作,但我可以使用基类使其跨多个实体工作。

为了满足我的第四个约束(使用解决方案 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”注册为没有元数据。

  • public abstract class Dateable使用上面的日志,但仍然运行代码:
    每当我从数据存储中创建或读取数据时,创建日期都会发生变化。

  • @PersistenceCapable public abstract class Dateable

    DataNucleus.MetaData 类“[...].MyEntity”已指定有 1 个主键字段,但此类使用数据存储标识并且应该是应用程序标识。

4

1 回答 1

0

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

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

于 2013-08-27T12:51:32.777 回答