2012-11-18 124 views
0

我在很多projets中使用Hibernate。自从我开发了我的项目以来,包括一个翻译表,其中包含每种语言的文本值,用于每个需要它的表。对于转换表Hibernate参数注入映射,可能吗?

<?xml version="1.0" encoding="UTF-8"?> 
<!DOCTYPE hibernate-mapping PUBLIC "-//Hibernate/Hibernate Mapping DTD 3.0//EN" "http://hibernate.sourceforge.net/hibernate-mapping-3.0.dtd"> 
<hibernate-mapping> 
    <class dynamic-insert="false" dynamic-update="false" mutable="true" name="com.spectotechnologies.website.common.helper.TranslationValue" optimistic-lock="version" polymorphism="implicit" select-before-update="false" table="common_translations"> 
    <id name="keyTranslation"> 
     <generator class="native"/> 
    </id> 
    <property name="keyLanguage"/> 
    <property name="tableName"/> 
    <property name="fieldName"/> 
    <property name="keyRow"/> 
    <property name="value"/> 
    </class> 
</hibernate-mapping> 

一个对象为例需要翻译

映射文件:

<?xml version="1.0" encoding="UTF-8"?> 
<!DOCTYPE hibernate-mapping PUBLIC "-//Hibernate/Hibernate Mapping DTD 3.0//EN" "http://hibernate.sourceforge.net/hibernate-mapping-3.0.dtd"> 
<hibernate-mapping> 
    <class dynamic-insert="false" dynamic-update="false" mutable="true" name="com.spectotechnologies.website.common.helper.Category" optimistic-lock="version" polymorphism="implicit" select-before-update="false" table="common_categories"> 
    <id name="keyCategory"> 
     <generator class="native"/> 
    </id> 
    <property name="keyParent"/> 
    <property name="tag"/> 
    <property name="name" insert="false" update="false"/> 
    <property name="description" insert="false" update="false"/> 
    </class> 
</hibernate-mapping> 

目前,我用这种SQL查询来加载对象

"SELECT" + 
    " c.keyCategory," + 
    " c.keyParent," + 
    " c.tag," + 
    " tn.value AS name," + 
    " td.value AS description" + 
" FROM common_categories c" + 
// name 
" LEFT JOIN common_translations tn" + 
    " ON tn.tableName = 'common_categories'" + 
    " AND tn.fieldName = 'name'" + 
    " AND tn.keyRow = c.keyCategory" + 
    " AND tn.keyLanguage = ?" + 
// description 
" LEFT JOIN common_translations td" + 
    " ON td.tableName = 'common_categories'" + 
    " AND td.fieldName = 'description'" + 
    " AND td.keyRow = c.keyCategory" + 
    " AND td.keyLanguage = ?" + 
" ORDER BY" + 
    " c.keyCategory ASC" 

我想知道是否有可能在映射内部传递这种左连接,为此我需要包含参数:tableName,fieldName,language。

您对此的帮助将非常感谢,我将能够简化大量查询!

编辑:

这里是我所期望的一个例子:

<?xml version="1.0" encoding="UTF-8"?> 
<!DOCTYPE hibernate-mapping PUBLIC "-//Hibernate/Hibernate Mapping DTD 3.0//EN" "http://hibernate.sourceforge.net/hibernate-mapping-3.0.dtd"> 
<hibernate-mapping> 
    <class dynamic-insert="false" dynamic-update="false" mutable="true" name="com.spectotechnologies.website.common.helper.Category" optimistic-lock="version" polymorphism="implicit" select-before-update="false" table="common_categories"> 
    <id name="keyCategory"> 
     <generator class="native"/> 
    </id> 
    <property name="keyParent"/> 
    <property name="tag"/> 
    <one-to-many class="com.spectotechnologies.website.common.helper.TranslationValue" 
    formula="tableName = 'common_categories' AND fieldName = 'name' AND keyLanguage = @language AND keyRow = keyCategory" name="name" /> 
    <one-to-many class="com.spectotechnologies.website.common.helper.TranslationValue" 
    formula="tableName = 'common_categories' AND fieldName = 'description' AND keyLanguage = @language AND keyRow = keyCategory" name="description" /> 
    </class> 
</hibernate-mapping> 

在这种情况下,我需要创建一个变量@language,可以在查询时被注入。这个解决方案有两个问题:

  1. 我不知道是否有可能将变量发布到映射范围。

  2. 公式是不存在的时刻:https://hibernate.onjira.com/browse/HHH-944

回答

0

由于使用“自定义关键字”(tableName和fieldName)来处理表格非常复杂,因此我将该关键字取反。现在需要多语言文本的对象具有所需文本的外键。它只需要为所有多语言数据的两个表:

CREATE TABLE `common_multilingualtexts` (
    `keyMultilingualText` int(11) NOT NULL auto_increment, 
    PRIMARY KEY (`keyMultilingualText`) 
) ENGINE=MyISAM AUTO_INCREMENT=0 DEFAULT CHARSET=utf8; 

CREATE TABLE `common_multilingualtexts_values` (
    `languageCode` varchar(5) NOT NULL, 
    `keyMultilingualText` int(11) NOT NULL, 
    `value` text, 
    PRIMARY KEY (`languageCode`,`keyMultilingualText`) 
) ENGINE=MyISAM DEFAULT CHARSET=utf8; 

MultilingualText是现在这个样子:

@Entity 
@Table(name = "common_multilingualtexts") 
public class MultilingualText implements Serializable 
{ 
    private Integer m_iKeyMultilingualText; 
    private Map<String, String> m_lValues = new HashMap<String, String>(); 

    public void setKeyMultilingualText(Integer p_iKeyMultilingualText) 
    { 
     m_iKeyMultilingualText = p_iKeyMultilingualText; 
    } 

    @Id 
    @GeneratedValue 
    @Column(name = "keyMultilingualText") 
    public Integer getKeyMultilingualText() 
    { 
     return m_iKeyMultilingualText; 
    } 

    public void setValues(Map<String, String> p_lValues) 
    { 
     m_lValues = p_lValues; 
    } 

    @ElementCollection(fetch = FetchType.EAGER) 
    @MapKeyColumn(name = "languageCode") 
    @CollectionTable(name = "common_multilingualtexts_values", joinColumns = @JoinColumn(name = "keyMultilingualText")) 
    @Column(name = "value") 
    public Map<String, String> getValues() 
    { 
     return m_lValues; 
    } 

    public void put(String p_sLanguageCode, String p_sValue) 
    { 
     m_lValues.put(p_sLanguageCode,p_sValue); 
    } 

    public String get(String p_sLanguageCode) 
    { 
     if(m_lValues.containsKey(p_sLanguageCode)) 
     { 
      return m_lValues.get(p_sLanguageCode); 
     } 

     return null; 
    } 
} 

而且每次需要使用多种语言只需要声明如下领域:

@OneToOne(cascade = CascadeType.ALL) 
@JoinColumn(name = "keyTitle") 
public MultilingualText getTitle() 
{ 
    return m_oTitle; 
} 

注:

唯一的缺点是每个多语言字段生成一个N + 1选择,一旦找到解决方案,我会更新我的答案。

0

对我来说,所有你需要的是定义一个一对多和多对多一个2个实体之间的关系。例如。每个类别应该有一个(或一组)翻译。

+0

当然,但如何注入语言参数?每种用户会话的语言都不相同。实际上,tableName和fieldName可以在映射中被硬编码,但不是语言。 –

+0

检索所有语言的所有翻译,但使用会话中定义的语言的唯一翻译 – StanislavL

+0

如果我需要从结果中丢弃未成文的翻译,则不会对其进行优化。明天我会看看是否有可能从查询中丢弃。 –