【问题标题】:One-to-many relationship children throw "One or more instances could not be made persistent"一对多关系孩子抛出“一个或多个实例无法持久化”
【发布时间】:2012-08-13 06:28:41
【问题描述】:

我有两个类,每个类都是 PersistentCapable——一个 Event 和一个 Score。 Event 类包含一个分数的 ArrayList。

我有一个建立事件列表的方法,然后尝试使用以下方法将事件及其相应的分数保存到数据存储区

PersistenceManager pm = PMF.get().getPersistenceManager();
        try {
            pm.makePersistentAll(Event.getEvents());
        } finally {
            pm.close();
        }

所有事件都很好地保存到数据存储区(我可以在 /_ah/admin 中看到它们)。 然而,分数不会保存(至少大多数不会保存)。

第一个事件保存的所有分数,但没有其他事件的分数。 所有事件都有分数,并且在尝试保存到数据存储之前填充列表。

我对@9​​87654324@ 的调用也正在抛出javax.jdo.JDOUserException: One or more instances could not be made persistent

最后,我可以在数据存储区管理员中看到,虽然所有事件都已保存,但它们的得分值是一堆 (~15) 空值的列表。所有其他值都是正确的。 键也是唯一的(虽然我是手动生成的)。

对出了什么问题有任何想法吗?

事件:

@PersistenceCapable(detachable="true")
public class Event {
    @NotPersistent
    protected static ArrayList<Event> events = new ArrayList<Event>();

    @PrimaryKey
    @Persistent
    private Key key;

    @Persistent
    private String name;
    @Persistent
    private String date;
    @Persistent
    private String year;
    @Persistent
    private String scoresUrl;
    @Persistent
    private ArrayList<Score> scores;

得分:

@PersistenceCapable(detachable="true")
public class Score {
    @PrimaryKey
    @Persistent
    private Key key;
    @Persistent
    private Key eventKey;
    @Persistent
    private String unitName;
    @Persistent
    private int place;
    @Persistent
    private float score;

在 logging.properties 中设置 .level = FINEST 后,我看到三个条目,我认为这三个条目可能会在所有事件都保存后导致问题。在makePersistentAll() 可以访问 Score 对象之前,似乎连接已关闭。

Aug 17, 2012 2:15:42 PM org.datanucleus.store.connection.ConnectionManagerImpl closeAllConnections
FINE: Connection found in the pool : com.google.appengine.datanucleus.DatastoreConnectionFactoryImpl$DatastoreManagedConnection@77a477b7 for key=org.datanucleus.ObjectManagerImpl@45e4d960 in factory=ConnectionFactory:nontx[com.google.appengine.datanucleus.DatastoreConnectionFactoryImpl@4eafccbe] but owner object closing so closing connection
Aug 17, 2012 2:15:42 PM org.datanucleus.store.connection.ConnectionManagerImpl$1 managedConnectionPostClose
FINE: Connection removed from the pool : com.google.appengine.datanucleus.DatastoreConnectionFactoryImpl$DatastoreManagedConnection@77a477b7 for key=org.datanucleus.ObjectManagerImpl@45e4d960 in factory=ConnectionFactory:nontx[com.google.appengine.datanucleus.DatastoreConnectionFactoryImpl@4eafccbe]
Aug 17, 2012 2:15:42 PM com.google.apphosting.utils.jetty.JettyLogger warn
WARNING: /scores
javax.jdo.JDOUserException: One or more instances could not be made persistent

【问题讨论】:

  • 这听起来可能很愚蠢,但是您是否尝试过在事务中进行持久化(即启动事务、持久化所有内容、提交事务)?
  • 不,我没有。从我看到的here 来看,我必须为要保存的每个对象创建 Entity 对象,这需要对我当前的代码进行一些修改,该代码尝试使用 Event 和 Score 对象本身。如果没有其他建议,我一定会试一试。
  • 您知道您不需要在所有这些字段上使用“@Persistent”吗?默认情况下,它们将是持久的。读取持久化进程日志(在 DEBUG 级别)会告诉你为什么会出现错误
  • 是的,我知道。但是,Defining Data Classes 页面的第一个提示建议明确地将所有字段注释为持久性,因为默认情况下有些不是持久性的。我最初并没有对它们全部进行注释,而是决定对它们进行注释以防万一出现问题。我用日志更新了帖子的结尾。

标签: java google-app-engine persistence jdo


【解决方案1】:

根据 Shivan Dragon 的建议,我从使用 PersistenceManager 转变为在事务中执行所有操作。

它看起来几乎没有那么整洁(因为我需要显式设置每个属性),但它现在可以按预期工作并且不再抛出异常。

我完全可以接受额外的混乱,因为这种方法还可以让我更好地控制何时以及何时不将单个实体的数据保存到数据存储区。

【讨论】:

    【解决方案2】:

    因为我遇到了同样的问题,所以我找到了这种解决方法。

    我使用 PersistenceManager 来查找我想要删除的所有持久对象。在此之后,我试图只删除第一个。例如:

    PersistenceManager pm = ...
    List<MyEntity> myEntityList = pm.newQuery(MyEntity.class).executeList();
    pm.deletePersistent(myEntityList.get(0));// Pretend that myEntityList has at least one object.
    

    这样你会得到另一个错误,告诉你这就是问题所在。从这第二个错误中,我了解到我需要删除外键上的非空约束。或者从这一点开始,您应该会看到 MySql 错误,而不是更多的 JDO 错误。

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 2017-01-10
      • 1970-01-01
      • 1970-01-01
      • 2017-12-31
      • 2019-01-25
      • 1970-01-01
      • 2012-12-17
      相关资源
      最近更新 更多