拥有一对一关系和父母/子女关系的问题

时间:2009-07-16 21:59:56

标签: database google-app-engine jdo

我有三个实体User,Company和Address,声明如下:

@PersistenceCapable(identityType = IdentityType.APPLICATION)
public class User implements Serializable {
  @PrimaryKey
  @Persistent(valueStrategy = IdGeneratorStrategy.IDENTITY)
  private Key key;

  @Persistent(mappedBy="creator")
  @Order(extensions = @Extension(vendorName="datanucleus", key="list-ordering", value="title asc"))
  private Collection<Company> companies;

  @Persistent
  private Address address;
  . . . 
}

public class Company implements Serializable {
  @PrimaryKey
  @Persistent(valueStrategy = IdGeneratorStrategy.IDENTITY)
  private Key key;

  @Persistent
  @Extension(vendorName="datanucleus", key="gae.parent-pk", value="true")
  private Key creatorKey;

  @Persistent
  private User creator;

  @Persistent
  private Address address;
  . . .
}

@PersistenceCapable(identityType = IdentityType.APPLICATION)
public class Address implements Serializable{
  @PrimaryKey
  @Persistent(valueStrategy = IdGeneratorStrategy.IDENTITY)
  private Key key;
  . . .
}

创建用户后,我会在设置地址和其他信息之后保留用户拥有的两家公司:

company.setCreatorKey(currentUser.getKey());
pm.makePersistent(company);

当我检索公司并从该对象引用创建者时出现问题。显然,JDO认为两家公司的地址属于用户,而不是公司,并记录以下错误:

address is mapped as a 1 to 1 relationship but there is more than one enity of kind Address that is a child of User(email@email.com) 

用户的关键是

User(email@email.com)

公司的关键是

User(email@email.com)\Company(1) 

并且两个地址的密钥是

User(email@email.com)\Company(1)\Address(1) 
User(email@email.com)\Company(1)\Address(2)

我对层次数据库很陌生,所以我想知道为什么这两个地址被持久化/解释为用户的子节点,而不是公司用户和子节点的后代。对于这种情况,正确的层次结构是什么?感谢。

1 个答案:

答案 0 :(得分:0)

您使用的是什么版本的应用引擎sdk?周一,他们发布了一个新版本,其中包含许多针对JDO问题的修复程序。 (release notes)四个或五个修复程序与对象之间的关系有关,所以这个问题可能已经解决,或以新方式破坏:) OTOH,您的问题可能与此公开ticket有关。

  

我对分层数据库很陌生,所以我想知道为什么这两个地址被持久化/解释为用户的子代,而不是用户和子公司的后代。

您看到的密钥层次结构基于实体组。就数据存储而言,您可以将您的公司放在与用户不同的实体组中,从而产生如下关键结构:

User(email@email.com)
Company(1)\Address(1) 
Company(1)\Address(2)

数据存储区不一定了解一对一映射或一对多映射。它只是让你引用你喜欢的其他实体的键。但是,JDO层会自动将所有实体置于同一实体组中,这可能是因为它可以强制执行以事务方式发生的更改。

说了这么多,你的结构看起来还不错。看起来JDO层只是检查具有类型地址的任何实体组后代,而不是专门查找公司的直接子项。