1

次の問題があります。これはキャッシングに関連していると思われますが、機能させることができません。

構成: Glassfish 3.1、JPA 2、EJB3.1、Eclipselink 2.2。

プロセス中に、いくつかの UpdatePackageFiles を含む UpdatePackage を生成します。これらのファイルは、親の UpdatePackage にリンクされていますが、それ自身との再帰的な関係もあります。たとえば、いくつかのファイルを含む ZIP バンドルであるパッケージがあります。このプロセスにより、データベースに UpdatePackage とファイルが作成されます。ここまでは順調ですね。

その後、2 番目のプロセスが開始されます (別のプロセス、新しいトランザクションなど)。そして、すべてのファイルを含む UpdatePackage を取得しますが、ここに問題があります。ファイル間の内部階層が完全ではありません。そのため、TOP UpdatePackageFile を取得すると、そのファイルには子が 1 つありますが、その子には子が含まれていませんが、2 つあるはずです。データベースは正しいことに注意してください。

アプリケーション サーバーを再起動して 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;
  }
}

したがって、私のクエリは明らかに正しいですが、それでも階層は不完全にフェッチされています。

4

1 に答える 1

0

関係の両側を維持する必要があります。ほとんどの場合、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を参照して ください。

于 2012-05-31T13:33:36.777 に答える