Nicktar
Nicktar

Reputation: 5575

Hibernate @ElementCollection - Better solution needed

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

Answers (1)

Nicktar
Nicktar

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

Related Questions