0

私は多くのプロジェクトで 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、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 を作成する必要があります。このソリューションには 2 つの問題があります。

  1. 変数をマッピング スコープに公開できるかどうかはわかりません。

  2. 式は今のところ存在しません: https://hibernate.onjira.com/browse/HHH-944

4

2 に答える 2

0

私にとって必要なのは、2 つのエンティティ間の 1 対多および多対 1 の関係を定義することだけです。たとえば、各カテゴリには翻訳のリスト (またはセット) が必要です。

于 2012-11-19T06:58:33.517 に答える
0

「カスタム キー」(tableName と fieldName) を使用してテーブルを操作するのは複雑だったので、キーを反転させました。多言語テキストを必要とするオブジェクトには、必要なテキストへの外部キーがあります。すべての多言語データに必要なテーブルは 2 つだけです。

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 の選択を生成することです。その解決策が見つかったら、回答を更新します。

于 2014-06-06T07:00:47.770 に答える