我有以下问题,我认为与缓存有关,但无法正常工作。

配置:Glassfish 3.1,JPA 2,EJB3.1,Eclipselink 2.2。

在一个过程中,我生成带有几个UpdatePackageFiles的UpdatePackage。这些文件链接到父UpdatePackage,但也具有与其自身的递归关系。
例如,我有一个Package,它是一个ZIP捆绑包,其中包含多个文件。
该过程在数据库中创建UpdatePackage和文件。到目前为止,一切都很好。

之后,第二个流程开始(不同的流程,新的交易等)。然后,我得到了包含所有文件的UpdatePackage,但问题是:文件之间的内部层次结构不完整。因此,如果我得到TOP UpdatePackageFile,则该文件有一个孩子,但是该孩子不包含任何孩子,尽管应该有2个孩子。注意,数据库是正确的。

如果重新启动应用程序服务器并再次运行第二个进程,则层次结构已完成。

我运行以下查询

Query query = em.createQuery("SELECT pck FROM UpdatePackageSubscription pck "
  + " LEFT JOIN FETCH pck.updatePackage"
  + " JOIN pck.updatePackage g LEFT JOIN FETCH g.updatePackageFiles "
  + " JOIN g.updatePackageFiles q LEFT JOIN FETCH q.updatePackageFiles"
  + " JOIN q.updatePackageFiles z LEFT JOIN FETCH z.updatePackageFiles"
  + " WHERE pck.subscription.eps.id = :id "
  + " AND pck.subscription.applicationSubcategory.shortName = :shortName"
  + " AND pck.status != :done AND pck.status != :obsolete "
  + " ORDER BY pck.updatePackage.id");

query.setParameter("id", id);
query.setParameter("shortName", shortName);
query.setParameter("done", UpdatePackageSubscriptionStatusType.DONE);
query.setParameter("obsolete", UpdatePackageSubscriptionStatusType.OBSOLETE);
query.setHint("javax.persistence.cache.storeMode", "REFRESH");


您可以看到我显式地运行较低级别的层次结构联接来强制进行提取。而且我还将缓存设置为REFRESH。我还将以下内容添加到我的persistence.xml中

<property name="eclipselink.query-results-cache" value="false" />


我有以下实体,所有实体均设置为EAGER提取。

@Entity
@Table(name = "UPDATE_PACKAGE_SUBSCRIPTION")
public class UpdatePackageSubscription implements Serializable {
  private UpdatePackage updatePackage;

  // bi-directional many-to-one association to UpdatePackage
  @ManyToOne(fetch = FetchType.LAZY, cascade = { CascadeType.ALL })
  @JoinColumn(name = "UPP_ID", nullable = false)
  public UpdatePackage getUpdatePackage() {
    return this.updatePackage;
  }

  public void setUpdatePackage(UpdatePackage updatePackage) {
    this.updatePackage = updatePackage;
  }
}

@Entity
@Table(name = "UPDATE_PACKAGE")
public class UpdatePackage implements Serializable {
  private List<UpdatePackageFile> updatePackageFiles = new ArrayList<UpdatePackageFile>();
  private List<UpdatePackageSubscription> updatePackageSubscriptions = new ArrayList<UpdatePackageSubscription>();

  @OneToMany(mappedBy = "updatePackage", fetch = FetchType.EAGER)
  @OrderBy
  public List<UpdatePackageFile> getUpdatePackageFiles() {
    return this.updatePackageFiles;
  }

  public void setUpdatePackageFiles(List<UpdatePackageFile> updatePackageFiles) {
    this.updatePackageFiles = updatePackageFiles;
  }

  // bi-directional many-to-one association to UpdatePackageSubscription
  @OneToMany(mappedBy = "updatePackage", cascade = { CascadeType.ALL })
  @PrivateOwned
  public List<UpdatePackageSubscription> getUpdatePackageSubscriptions() {
    return this.updatePackageSubscriptions;
  }

  public void setUpdatePackageSubscriptions(List<UpdatePackageSubscription> updatePackageSubscriptions) {
    this.updatePackageSubscriptions = updatePackageSubscriptions;
  }
}

@Entity
@Table(name = "UPDATE_PACKAGE_FILE")
public class UpdatePackageFile implements Serializable {
  private UpdatePackage updatePackage;
  private UpdatePackageFile updatePackageFile;
  private List<UpdatePackageFile> updatePackageFiles;

  // bi-directional many-to-one association to UpdatePackage
  @ManyToOne(fetch = FetchType.EAGER)
  @JoinColumn(name = "UPP_ID", nullable = false)
  public UpdatePackage getUpdatePackage() {
    return this.updatePackage;
  }

  public void setUpdatePackage(UpdatePackage updatePackage) {
    this.updatePackage = updatePackage;
  }

  // bi-directional many-to-one association to UpdatePackageFile
  @ManyToOne(fetch = FetchType.EAGER)
  @JoinColumn(name = "PARENT_FILE_ID")
  public UpdatePackageFile getUpdatePackageFile() {
    return this.updatePackageFile;
  }

  public void setUpdatePackageFile(UpdatePackageFile updatePackageFile) {
    this.updatePackageFile = updatePackageFile;
  }

  // bi-directional many-to-one association to UpdatePackageFile
  @OneToMany(mappedBy = "updatePackageFile", fetch = FetchType.EAGER)
  @PrivateOwned
  @OrderBy
  public List<UpdatePackageFile> getUpdatePackageFiles() {
    return this.updatePackageFiles;
  }

  public void setUpdatePackageFiles(List<UpdatePackageFile> updatePackageFiles) {
    this.updatePackageFiles = updatePackageFiles;
  }
}


因此,我的查询显然是正确的,但仍未完全获取层次结构。

最佳答案

您必须维护关系的双方。您很可能设置了ManyToOne,但未将其添加到OneToMany中。

看到,
http://en.wikibooks.org/wiki/Java_Persistence/Relationships#Object_corruption.2C_one_side_of_the_relationship_is_not_updated_after_updating_the_other_side

您也可以禁用共享缓存,但是您的代码仍然会出错,并且仍然会在持久性上下文中破坏对象。

看到,
http://wiki.eclipse.org/EclipseLink/FAQ/How_to_disable_the_shared_cache%3F

07-24 15:40