使用常量键的Hibernate地图集合

时间:2009-11-17 15:45:05

标签: hibernate map collections key

我正在尝试使用外键和固定值映射集合(类型映射)作为键/映射参数。

我有几个产品类型表和一个包含产品名称等内容的语言表。

现在假设我们有一个附件表(显然)包含附件,然后附件的名称存储在语言表中,其中包含language.id = accessory.id和language.type ='accessory'。 map-key应该是language.lang字段,一个语言代码字符串。

现在,无论我尝试过什么,我都无法将“language.type ='accessory'”部分放在右边,不喜欢多个关键元素,反过来又不允许使用元素。

我也尝试使用复合组件作为foreignKey,默认情况下设置常量,但这样做也不起作用:

<class name="AccessoryTypes"
    table="accessorytypes">
    <id name="id" column="id" type="java.lang.Long" unsaved-value="0">
        <generator class="identity"></generator>
    </id>
    <map name="Name" table="ProductCode">
        <key column="CompositeId" />
        <map-key column="Language" type="string" />
        <one-to-many class="ProductCode" />
    </map>
</class>

<class name="Language"
        table="Language">
        <composite-id name="compositeId" class="languageKey">
            <key-property name="Type"></key-property>
            <key-property name="Id"></key-property>
        </composite-id>
        <property name="Lang" type="string"></property>
        <property name="Value"></property>
    </class>

当然有适当的课程。这种方法没有错误,但是没有填充Accessory类的HashMap ......

任何帮助都将不胜感激,谢谢。

[编辑] 我现在尝试使用property-ref作为ziodberg建议,首先是不是这样的:

<class name="AccessoryTypes"
        table="accessorytypes">
    <id name="id" column="id" type="java.lang.Long" unsaved-value="0">
        <generator class="identity"></generator>
    </id>
    <properties name="CompositeId" >
        <property name="id" />
        <property name="Type" formula="'accessory'" />
    </properties>
    <map name="Name" table="ProductCode">
        <key property-ref="CompositeId" />
        <map-key column="Language" type="string" />
        <one-to-many class="ProductCode" />
    </map>
</class>

<class name="com.swissclick.wesco.web.model.ProductCode"
        table="ProductCode">
    <composite-id  class="com.swissclick.wesco.web.model.ProductCodeKey" mapped="true">
        <key-property name="Type"></key-property>
        <key-property name="id"></key-property>
    </composite-id>
    <property name="Language" type="string"></property>
    <property name="Value"></property>
</class>

但这也不起作用,它给出了

org.hibernate.MappingException: collection foreign key mapping has wrong number of columns: AccessoryTypes.Name type: component[Id,Type]

没有在谷歌上发现任何有用的信息。

任何想法?

1 个答案:

答案 0 :(得分:2)

<强>被修改即可。所以我对你的桌面结构还不太清楚 - 这就是我在写下初步答案时抛出的东西。

我的理解是你的Language表看起来像:

Id -- this is a PK of entity (e.g. Accessory) this entry provides localization info for
Type -- string constant describing entity type (e.g. "accessory")
Language -- language code
Value -- actual localized string

看起来对吗?如果是这样,这会引发一个问题,即您打算如何在同一实体中本地化多个字段。你不应该至少有另一列链接到属性(字段)名称吗?

无论如何,<formula>确实不支持<key>作为type的一部分(我可能已经宣誓就是这样),所以你在这里的选择非常有限:

  1. 使用custom loader - 这可能是最简单的方法。
  2. Accessory表格中添加Language作为实际列,并将其作为复合ID的一部分进行映射;然后,您可以使用复合键映射get()地图。应该工作,但相当丑陋。
  3. 重新思考你的方法。您真的每次都需要加载语言地图吗?似乎将它作为一个单独的查询(或者直接Language,假设适当的复合ID),当前语言更容易,并且(有足够的缓存配置)更快。
  4. 更新详细说明上述#3:

    首先,让我澄清一下 - 我假设您的本地化字符串在运行时是用户可编辑的。如果情况并非如此,我强烈建议完全放弃该表,而是使用资源包。

    我将type映射为一个单独的实体idlanguageproperty_name和(如果您需要为多个属性执行此操作){{1} }作为复合id的一部分。您实体的实际可本地化属性(例如ProductName上的AccessoryType)将是暂时的。然后,您可以通过执行以下操作手动为实体加载适当的本地化字符串:

    AccessoryType accessory = ...;
    Language language = (Language) session.get(Language.class,
     new LanguageKey("accessory", accessory.id, "en_US", "productName"));
    accessory.setProductName(language.getValue());
    

    你甚至可以在event listener中做到这一点,假设当前选择的语言是全局可获得的(通过全局或线程本地调用) - 它将自动神奇地发生在你所有的实体上。 如果语言表相当小,您可以使用Hibernate cache it,甚至不会对此产生数据库命中。