【问题标题】:Hibernate parameters injection inside mapping, possible?映射内部的休眠参数注入,可能吗?
【发布时间】:2012-11-18 23:27:03
【问题描述】:

我在许多项目中使用 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"

我想知道是否可以在映射中传输这种 LEFT JOINS,为此我需要包含参数:tableName、fieldName、语言。

非常感谢您的帮助,我将能够简化很多查询!

编辑:

这是我期望的一个例子:

<?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

【问题讨论】:

    标签: java mysql hibernate hibernate-mapping


    【解决方案1】:

    对我来说,您只需定义两个实体之间的一对多和多对一关系。例如。每个类别都应该有翻译列表(或集合)。

    【讨论】:

    • 当然,但是如何注入语言参数?每个用户会话的语言都不同。实际上 tableName 和 fieldName 可以在映射中硬编码,但不能在语言中。
    • 检索所有语言的所有翻译,但使用会话中定义的语言的唯一翻译
    • 如果我需要从结果中丢弃不需要的,它不会被优化。明天我会看看是否可以从查询中丢弃。
    【解决方案2】:

    由于使用“自定义键”(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 选择,一旦找到解决方案,我会更新我的答案。

    【讨论】:

      猜你喜欢
      • 2023-04-02
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多