Reputation: 5575
I'm using Hibernate 3.5.a-Final as ORM-Layer in a web application. I've got several Beans with the same code-sniplet wich makes me think that this design isn't the best one around. But I can't figure out how to implement a better one in hibernate.
Requirements
Current solution (doesn't solve the last requirement)
Each class contains a HashMap annotated as
@ElementCollection(fetch=FetchType.EAGER)
@CollectionTable(name = "localized[X]Descriptions", joinColumns = @JoinColumn(name = "id"))
@MapKeyJoinColumn(name = "locale")
public Map<Locale, String> getLocalizedDescriptions() {
return localizedDescriptions;
}
[X] beeing the name of the class
For Each class the is an additional table (generated by hibernate)
create table localized[X]Descriptions (
id integer not null,
localizedDescriptions varchar(255),
localizedDescriptions_KEY varchar(255),
primary key (id, localizedDescriptions_KEY)
)
For some reason the @MapKeyJoinColumn
gets ignored...
What I'd prefer would be a single table like this:
create table localizedDescriptions (
class varchar(255) not null,
id integer not null,
locale varchar(50) not null,
description varchar(255) not null,
primary key (class, id, locale)
)
It would be a big plus if the implementation would be queryable using the criteria-api (which isn't compatible to @ElementCollection
s as far as I know).
But I can't figure out how to implement this. Any pointers would be very welcome
Upvotes: 3
Views: 2632
Reputation: 5575
I found my own solution...
I just use
@Entity
@Inheritance(strategy = InheritanceType.SINGLE_TABLE)
@DiscriminatorColumn(name="masterClass", discriminatorType=DiscriminatorType.INTEGER)
@Table(name="localizedDescriptions")
public class LocalizedDescriptions{
private Integer id;
private Locale locale;
private String description;
[Getters, Setters]
}
as my parent-class for all localized descriptions and extend it like
@Entity
public class LocalizedSomeDescription extends LocalizedDescription {
private Some master;
/**
* @return the master
*/
@ManyToOne
public Some getMaster() {
return master;
}
Which gets used like this:
@Table
@Entity
public class Some {
private Map<Locale, LocalizedSomeDescription> names = new HashMap<Locale, LocalizedSomeDescription>();
@OneToMany
@JoinColumn(name="master_id")
@MapKeyColumn(name="locale")
public Map<Locale, LocalizedSomeDescription> getDescriptions() {
return descriptions;
}
}
This results in something very similar to my intended table design
create table localizedDescriptionss (
masterClass integer not null,
id integer not null auto_increment,
locale varchar(255),
description varchar(255),
master_id integer,
primary key (id)
)
using mappedBy="master" in all subclasses might seem like an abuse of hibernate inheritance but all other solutions would include one row per subclass which would be null in every other, which seems to me like a very bad table design. I still have to find out what's the 'sensible default' for a discriminatorType=DiscriminatorType.INTEGER
and if I need to override that default.
Upvotes: 2