English 中文(简体)
Hibernate map collection with constant key
原标题:

I m trying to map a collection (of type map) using a foreign key and a fixed value as the key/mapping arguments.

I have several tables of product types and a language table which holds stuff like product names and so on.

Now let s say we have an Accessory table which holds (obviously) accessories, then the name of an accesory is stored in the language table with language.id = accessory.id and language.type= accessory . The map-key should be the language.lang field, a language-code string.

Now, no matter what I ve tried, I just can t get the "language.type= accessory " part right, doesn t like multiple key element, which in turn wouldn t allow elements anyways.

I ve also tried it with a composite component as foreignKey, with the constant set by default, but that didn t really work either:

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

of course with the appropriate classes. This approach gives no error, but doesn t fill the HashMap of the Accessory class either...

any help would be appreciated, thanks.

[edit] I now tried it with property-ref as ziodberg suggested, first with a not with like this:

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

and

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

but this doesn t work, either, it gives

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

which doesn t turn up any helpful information on google.

any ideas?

最佳回答

Edited. So I m still not quite clear on your table structure - that s what has thrown me when I wrote the initial answer.

My understanding is that your Language table look something like:

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

Does that look about right? If so, this raises the question on how you intend to localize multiple fields within the same entity. Shouldn t you at least have another column linking to property (field) name?

At any rate, <formula> is indeed not supported as part of the <key> (I could have sworn that is is) so your options here are pretty limited:

  1. Use a custom loader - this is probably the most straightforward approach.
  2. Add type as an actual column on your Accessory table and map it as part of composite id; you can then map Language map using composite key. Should work but is rather ugly.
  3. Rethink your approach. Do you really need to load a map of languages every time? Seems like doing it as a separate query (or even direct get() assuming appropriate composite id) for current language would be easier and (with adequate caching configuration) a lot faster.

Update To elaborate on #3 above:

First of, let me clarify this - I m assuming your localized strings are user-editable at runtime. If that s not the case, I d strongly recommend forgoing the table altogether and going with resource bundles instead.

I d map Language as a separate entity with type, id, language and (if you need to do this for multiple properties) property_name as parts of composite id. The actual localizable property on your entity (e.g. ProductName on AccessoryType) would be transient. You can then manually load the appropriate localized string for your entity by doing something like:

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

You can even do that in the event listener assuming that currently selected language is globally obtainable (via global or thread local call) - it will then happen auto-magically for all you entities. If the language table is reasonably small, you can have Hibernate cache it and you won t even incur database hits on this.

问题回答

暂无回答




相关问题
Multiple Hibernate instances using C3P0

I am facing a weird problem and it seems to be c3p0 related. I am starting two instances of an app in the same java vm which interact with each other. After some operations "APPARENT DEADLOCK" ...

Hibernate vs Ibatis caching

We can speed up a hibernate app easyly with 2nd level cache using infinispan or ehcache/terracotta,... but ibatis only have a simple interface to implement for caching. And hibernate knows more ...

Using annotations to implement a static join in hibernate

I m relatively new to hibernate and was wondering if someone could help me out. While I have no issues implementing a normal join on multiple columns in hibernate using the @JoinColumns tag, I m ...

Hibernate query with fetch question

I have a 2 entities in a One-To-Many relationship: OfficeView.java: public class OfficeView implements java.io.Serializable { private Integer officeId; private String addr1; private ...

hibernate interceptors : afterTransactionCompletion

I wrote a Hibernate interceptor : public class MyInterceptor extends EmptyInterceptor { private boolean isCanal=false; public boolean onSave(Object entity, Serializable arg1, Object[] arg2, String[]...

How to prevent JPA from rolling back transaction?

Methods invoked: 1. Struts Action 2. Service class method (annotated by @Transactional) 3. Xfire webservice call Everything including struts (DelegatingActionProxy) and transactions is configured ...

Hibernate/GORM: collection was not processed by flush()

I have an integration test in my Grails application that fails when I try to save an entity of type Member invitingMember.save(flush: true) This raises the following exception org.hibernate....

Hibernate Criteria API equivalent for "elements()"

Is it possible to implement the following query using Criteria API? select order from ORDER as order,ITEM as item where item.itemID like ITM_01 and item in elements(order.items)

热门标签