2012-10-18 33 views
1

我建立使用JPA /休眠+春JPA類別和語言的關係

我目前建這三豆/實體基於分類的Web應用程序的多語言:類別,CategoryLanguage和語言。

類別:

@Entity 
public class Category implements Serializable { 
    @Id 
    @GeneratedValue(strategy = GenerationType.AUTO) 
    private int id; 
    @ManyToOne 
    private Category father; 
    @OneToMany(mappedBy = "father") 
    private List<Category> children; 
    @OneToMany(mappedBy="category") 
    private List<CategoryLanguage> categoryLanguages; 

CategoryLanguage:

@Entity 
public class CategoryLanguage implements Serializable { 
    @Id 
    @GeneratedValue(strategy = GenerationType.AUTO) 
    private int id; 
    @ManyToOne 
    Category category; 
    @Column(length = 20, nullable = false) 
    private String name; 
    @ManyToOne 
    private Language language; 

語言

public class Language implements Serializable { 
    private static final long serialVersionUID = 1L; 
    @Id 
    @Column(length=2) 
    private String id; // en, de, fr, it, es,... 

    @Column(length=25) 
    private String name; // English, Deutsch, Français,... 

通過呼喚g

from Category c join c.categoryLanguages cl where c.father = null and cl.language.id = :lang 

它用正確的語言返回第一級類別,但包含所有語言作爲子級。

爲每種語言提取兒童,而不是我在查詢中選擇的兒童。

我能做些什麼來解決這個問題?我不能在JPQL中使用「加入」,我可以嗎?

+0

是否需要在子節點中初始化'new ArrayList()'? – CycDemo

+0

你想用語言檢索類別及其子類別(遞歸)嗎? – CycDemo

+0

沒有可能它不是,我會刪除它。 是的在第二個問題:) – ianaz

回答

1

您的查詢要求的完整類別的實體,所以你不能完成你想要JPA嚴格的。 JPA要求返回的類別實體反映數據庫中的數據 - 這包括所有的CategoryLanguage,而不管它們在選擇查詢中可能對應的語言。

你可能想要做的是改變查詢的方式。在這種情況下,請查詢與您想要的語言相關聯的CategoryLanguage實體,然後使用它來獲取類別。 category-> CategoryLanguage關係仍然會被填充,但是您的查詢僅返回表示您希望使用的語言的CategoryLanguage而不使用任何其他語言。如果需要,請按類別鍵入這些內容以使其更容易。

大多數提供程序允許直接向映射添加過濾標準,或者甚至可以使用僅返回部分實體的查詢,但我警告您避免沿着該路線行進。一旦這樣做,就很難維護應用程序並正確管理數據,並最終會限制性能選項,如緩存。例如,一旦你擁有了所有的部分類別實體並且想要添加一個新的類別語言或進行其他更改,那麼你如何處理它?合併將不起作用,因爲它會導致任何類別語言不在數據庫中的列表中

+0

寫得很好並且完整的答案,謝謝 – ianaz

0

確保使用如下FetchType.EAGER

用途:

SELECT c FROM Cagegory c INNER JOIN c.categoryLanguages l WHERE c.father = null AND l.id = :languageId 

@OneToMany(mappedBy = "father", fetch = FetchType.EAGER) 
private List<Category> children = new ArrayList(); 
@OneToMany(mappedBy="category", fetch = FetchType.EAGER) 
private List<CategoryLanguage> categoryLanguages = new ArrayList(); 
+0

謝謝,但與兩個EAGER它拋出MultipleBagFetchException:不能同時獲取多個行李。 通過僅在categoryLanguages上設置EAGER,它仍然加載所有語言的categoryLanguages:S – ianaz