2012-05-30 30 views
1

我有以下問題,我認爲這是與緩存有關,但我無法讓它工作。Eclipselink提取遞歸實體給出不完整的結果

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

在一個過程中,我用幾個UpdatePackageFiles生成一個UpdatePackage。這些文件鏈接到父UpdatePackage,但也有自己的遞歸關係。 例如,我有一個包是幾個文件的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"); 

你可以看到我明確地運行一個較低的層次結構加入強制提取。我還將緩存設置爲刷新。我還添加了以下內容到我的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; 
    } 
} 

所以,我的查詢顯然是正確的,但仍然不完整地提取層次結構。

回答

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

+0

PFF,我知道,我有這樣實現的,但我忘了一個地,這引起了混亂。謝謝! –