2011-05-11 105 views
2

爲了解決Java EE 6項目中對本地化動態(用戶創建,存儲在數據庫中)數據的需求,我製作了一個通用本地化字符串表,該表能夠存儲任何語言的任何字符串。這樣可以避免必須製作大約15個額外的表格,只是包含名稱的東西。我想知道的是兩兩件事:JPA中可本地化的字符串

1)你認爲這是一個很好的理念,爲什麼? 2)您是否知道在Cons中列出的問題的任何清潔解決方案?

我的經驗:

優點:只有一個表需要的,通用的解決方案,易於無論是在JPA和DB配置。重複的代碼是不存在的。

缺點:最大的問題,我覺得是由於muiltilingual_string表現在知道什麼對象是使用它,級聯刪除將無法從SQL工作(但它在JPA工作與orphanRemoval)。如果從JPA之外工作,這會產生「死」字符串保留在數據庫中的可能性。

的實體:(AbstractEntity是含有@id和@version映射超)

@Entity 
@Table(schema = "COMPETENCE", name = "multilingual_string") 
public class MultilingualString extends AbstractEntity{ 

    @ElementCollection(fetch=FetchType.EAGER) 
    @MapKey(name = "language") 
    @CollectionTable(schema = "COMPETENCE", name = "multilingual_string_map", 
        joinColumns = @JoinColumn(name = "string_id")) 
    private Map<Language, LocalizedString> map = new HashMap<Language, LocalizedString>(); 

    public MultilingualString() {} 

    public MultilingualString(Language lang, String text) { 
     addText(lang, text); 
    } 

    public void addText(Language lang, String text) { 
     map.put(lang, new LocalizedString(lang, text)); 
    } 

    public String getText(Language lang) { 
     if (map.containsKey(lang)) { 
      return map.get(lang).getText(); 
     } 
     return null; 
    } 

    public LocalizedString getLocalizedString(Language lang){ 
     if(map.get(lang) == null) 
      map.put(lang, new LocalizedString(lang, null)); 
     return map.get(lang); 
    } 

    @Override 
    public MultilingualString clone(){ 
     MultilingualString ms = new MultilingualString(); 
     for(LocalizedString s : map.values()) 
      ms.addText(s.getLanguage(), s.getText()); 
     return ms; 
    } 

    @Override 
    public String toString() { 
     return getId() == null ? "null " + this.getClass().getName() : getId().toString(); 
    } 
} 

@Embeddable 
public class LocalizedString { 

    @JoinColumn(name="lang_id") 
    private Language language; 

    @Column(name="text") 
    private String text; 

    public LocalizedString() { 
    } 

    public LocalizedString(Language language, String text) { 
     this.language = language; 
     this.text = text; 
    } 

    public Language getLanguage() { 
     return language; 
    } 

    public void setLanguage(Language language) { 
     this.language = language; 
    } 

    public String getText() { 
     return text; 
    } 

    public void setText(String text) { 
     this.text = text; 
    } 

} 

的類用於象在其它實體以下:

@OneToOne(cascade=CascadeType.ALL, orphanRemoval=true) 
@JoinColumn(name = "summary_stringid") 
private MultilingualString summary; 

的表格:

MULTILINGUAL_STRING (
    id bigint primary key 
); 

MULTILINGUAL_STRING_MAP (
    string_id bigint FOREIGN KEY REFERENCES MULTILINGUAL_STRING(id), 
    lang_id bigint FOREIGN KEY REFERENCES LANG(id), 
    text varchar(2000 char), 
    PRIMARY KEY(string_id, lang_id) 
); 

使用如下:

COMPETENCE (
    id bigint PRIMARY KEY, 
    name_id bigint FOREIGN KEY REFERENCES MULTILINGUAL_STRING(id) 
); 

回答

1

我看到的一個問題是,這似乎不像級聯的ResourceBundle。

在ResourceBundle中,如果您的語言環境是ES_es,它將首先在ES_es中查找本地化版本,如果它未找到,則在ES中嘗試,如果不是,則會查找默認字符串(如果它失敗,將顯示#STRING_ID字符串)。你可以有一個.EN字典,一個用於英國特定表達式的.EN_uk,一個用於表達美國特定表達式的.EN_us,而EN_uk和EN_us只能放置所需的鍵。

在您的系統中,它僅查看當前語言環境而不允許使用所有這些選項,因此您必須重新定義每個語言環境的所有值。因此,在上例中,您必須爲EN_uk和EN_us中的每個鍵都設置一個值。

+0

在我的情況,包括不同的語言環境感覺有點小題大做,因爲它只能處理純文本,最有可能的不要超越使用兩種語言。 – 2011-05-11 12:44:39