-->
These old forums are deprecated now and set to read-only. We are waiting for you on our new forums!
More modern, Discourse-based and with GitHub/Google/Twitter authentication built-in.

All times are UTC - 5 hours [ DST ]



Forum locked This topic is locked, you cannot edit posts or make further replies.  [ 4 posts ] 
Author Message
 Post subject: Object with two embedded components of the same class
PostPosted: Fri May 16, 2008 3:04 pm 
Beginner
Beginner

Joined: Wed Dec 20, 2006 11:21 am
Posts: 20
Hello, I'd like to store objects that can have i18n data string properties. Eg, their properties can be stored in different locales. I have created the following class (it's actually Groovy code and annotations, it does not make much difference though)

import javax.persistence.*
import org.hibernate.annotations.*

@Embeddable
class LocalizedString
{
@CollectionOfElements(targetElement = String.class)
@JoinTable(name = "language_string", joinColumns = [@JoinColumn(name = "localized_string_id")])
@org.hibernate.annotations.MapKey(targetElement = String.class, columns = [@Column(name="language")])
@Column(name = "translation")
Map <String, String> translations = new HashMap <String, String>();
}

So as you see this class has a Map<String, String>, basically a map with locale codes as key and actual localized messages as values. So far so good.

But now I'd like to map a class containing a LocalizedString component. I am stuck. Consider the following:

import javax.persistence.*
import org.hibernate.annotations.*

@Entity
@Table(name="test_i18n")
class TestI18N
{
@Id
@GeneratedValue(strategy = javax.persistence.GenerationType.IDENTITY)
Long id

@Version
Long version

@Embedded
LocalizedString someText

@Embedded
LocalizedString otherText
}

When I do this, I can see that the generated table mappings are not good. The test_i18n table is empty except for id and version, and the language_string join table contains only 3 columns, 2 of them corresponding to the Map values and keys, and the last is for the localized_string_id. This obviously will not work as it won't even be able to distinguish someText from otherText.

eg: CREATE TABLE IF NOT EXISTS `language_string` (
`localized_string_id` bigint(20) NOT NULL,
`translation` varchar(255) default NULL,
`language` varchar(255) NOT NULL default '',
PRIMARY KEY (`localized_string_id`,`language`),
KEY `FKBE5ED6D86DF0AA15` (`localized_string_id`)
)

CREATE TABLE IF NOT EXISTS `test_i18n` (
`id` bigint(20) NOT NULL auto_increment,
`version` bigint(20) default NULL,
PRIMARY KEY (`id`)
)

I think the only way to do this is via another table, linking test_i18n to the
language_string table. Exactly as if we were not using a component but an entity (then LocalizedString would have its own table). But I'd really like to use a component...

Can someone help me with the correct mapping (using annotations if possible) for what I want to achieve? It's explicitly stated on the Hibernate documentation that components can have arbitrary properties, so a Map property should be ok. On the Java persistence with Hibernate book, I did not find any examples or help for this (there is a nice complex example with a collection of components, but what I want here is different...)

Thanks for helping,

Jean-Noel

PS: I have found by Googling an article by Gavin about using i18n with a custom Hibernate type, but I don't want this kind of approach.


Top
 Profile  
 
 Post subject:
PostPosted: Sun May 18, 2008 11:28 am 
Beginner
Beginner

Joined: Wed Dec 20, 2006 11:21 am
Posts: 20
Throughout the week end I did some more testing and research. It now appears to me that the mapping within the embedded component is correct.

The troubles come from the fact that we have two embedded components of the same class. In the table containing the embedded map data, a row cannot discriminate between which of the properties in the container class it belongs to...

As I said, if I was dealing with entities this would be fine as I would have a unidirectional one to one association on another table. This would discriminate between the two properties.

But with a component, there is no such additional table, so how to deal with this? Is it at all possible? I would really appreciate some help.

Jean-Noel

PS: during my research it occured to me that it's for example also impossible to map TWO bidirectional one-to-one associations to the same class. Unidirectional is OK though (eg, the problem is navigating from the target object to the container object as you cannot discriminate to which property you belong). Can someone comment on this and supply a workaround? (again, maybe there is simply none).

PS2: changed the topic to better reflect the real problem


Top
 Profile  
 
 Post subject:
PostPosted: Mon May 19, 2008 1:48 pm 
Beginner
Beginner

Joined: Wed Dec 20, 2006 11:21 am
Posts: 20
bump


Top
 Profile  
 
 Post subject:
PostPosted: Wed Oct 29, 2008 1:58 pm 
Newbie

Joined: Tue Dec 20, 2005 4:59 pm
Posts: 1
I hope I'm not too late to answer you. you can simply use the @AttributeOverrides to override the names of the attributes in your class that holds the embeddable. You can see an example for that in page 12 of the Hibernate Annotation Reference Guide version 3.4.0.GA. An example for your case would be:

Code:
@Embedded
LocalizedString someText

@Embedded
@AttributeOverrides({
    @AttributeOverride(name="translations", column = @Column(name="otherTextTranslations") )
})
LocalizedString otherText


Of course you can add the @AttributeOverrides annotation to all embedded components, which would be a good thing so that you can name the fields in the database with names that reflect the meaning of this particular field in this particular table, and so on.

The previous solution will not work if you have a relation between a property in the embeddable component and an entity. I'm playing around with this, but currently, I don't have enough time to go deeply in that, especially that I don't need that. If I get back to it and find a way to have several embedded components that have foreign keys in other entities, I'll post the method here.


Top
 Profile  
 
Display posts from previous:  Sort by  
Forum locked This topic is locked, you cannot edit posts or make further replies.  [ 4 posts ] 

All times are UTC - 5 hours [ DST ]


You cannot post new topics in this forum
You cannot reply to topics in this forum
You cannot edit your posts in this forum
You cannot delete your posts in this forum

Search for:
© Copyright 2014, Red Hat Inc. All rights reserved. JBoss and Hibernate are registered trademarks and servicemarks of Red Hat, Inc.