Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How to build ElementCollection of Embeddable type?

I'm using Hibernate 3.5.6 as my JPA 2.0 implementation. I'm attempting to build an @ElementCollection inside my entity (many fields omitted):

@Entity
public class Buyer implements Serializable {
    ...
    @ElementCollection
    private List<ContactDetails> contacts;
    ...
}

I've made this work quite easily when the collection contains a basic type, but my ContactDetails is an @Embeddable class:

@Embeddable
public class ContactDetails implements Serializable {
    ...
    @Column(nullable = false)
    private String streetOne;
    ....
}

When I run let Hibernate generate the DDL, I get errors like this:

INFO  - Environment                - Hibernate 3.5.6-Final
....
INFO  - Version                    - Hibernate EntityManager 3.5.6-Final
....
INFO  - SettingsFactory            - RDBMS: PostgreSQL, version: 8.4.2
INFO  - SettingsFactory            - JDBC driver: PostgreSQL Native Driver, version: PostgreSQL 9.0 JDBC4 (build 801)
INFO  - Dialect                    - Using dialect: org.hibernate.dialect.PostgreSQLDialect
....
ERROR - SchemaUpdate               - Unsuccessful: create table Buyer_contacts (Buyer_id int8 not null, contacts_collection&&element_county varchar(255), contacts_collection&&element_email varchar(255), contacts_collection&&element_fax varchar(255), contacts_collection&&element_mainphone varchar(255) not null, contacts_collection&&element_mobile varchar(255), contacts_collection&&element_name varchar(255) not null, contacts_collection&&element_postcode varchar(255) not null, contacts_collection&&element_streetone varchar(255) not null, contacts_collection&&element_streettwo varchar(255), contacts_collection&&element_town varchar(255) not null)
ERROR - SchemaUpdate               - ERROR: syntax error at or near "&&"  Position: 73

Is there a way to persuade Hibernate to generate valid column names in the table for the collection class? Ideally, a way that doesn't violate the Don't Repeat Yourself principle by specifying each individual column name.

like image 502
Adrian Cox Avatar asked Mar 11 '11 14:03

Adrian Cox


People also ask

Can the embeddable class contain another embeddable class?

Embeddable classes may also contain relationships to other entities or collections of entities. If the embeddable class has such a relationship, the relationship is from the target entity or collection of entities to the entity that owns the embeddable class.

Which technique is used by Hibernate to persist collection of embeddable types?

Just like the collection of basic type, a collection of embeddable class can be persisted by using @ElementCollection on the collection reference in the entity class.

What is @ElementCollection?

JPA 2.0 defines an ElementCollection mapping. It is meant to handle several non-standard relationship mappings. An ElementCollection can be used to define a one-to-many relationship to an Embeddable object, or a Basic value (such as a collection of String s).

What is embeddable object in Java?

Defines a class whose instances are stored as an intrinsic part of an owning entity and share the identity of the entity. Each of the persistent properties or fields of the embedded object is mapped to the database table for the entity.


2 Answers

Alternative workaround using @AttributeOverrides :

/**
 * <!-- begin-user-doc --> <!-- end-user-doc --> <!-- begin-model-doc -->
 * User assignments (place managers, staffs, etc.). <!-- end-model-doc -->
 * 
 */
@ElementCollection()
// Workaround for https://hibernate.atlassian.net/browse/HHH-6005
@AttributeOverrides({
    @AttributeOverride(name="personId", column=@Column(name="personId")),
    @AttributeOverride(name="placeRoleId", column=@Column(name="placeRoleId"))
})
private Set<PlaceMember> members = new HashSet<PlaceMember>();
like image 80
Hendy Irawan Avatar answered Sep 29 '22 11:09

Hendy Irawan


It's a bug in Hibernate caused by incompatibility of DefaultComponentSafeNamingStrategy with @ElementCollection implementation details.

.collection&&element. is an internal placeholder that should be removed before use of property name as a column name. Other naming strategies effectively remove it by using only the part of property name after the last ., whereas DefaultComponentSafeNamingStrategy replaces .s with _s but doesn't remove the placeholder.

If you actually need DefaultComponentSafeNamingStrategy, here is a workaround:

public class FixedDefaultComponentSafeNamingStrategy extends DefaultComponentSafeNamingStrategy {
    @Override
    public String propertyToColumnName(String propertyName) {
        return super.propertyToColumnName(
            propertyName.replace(".collection&&element.", "."));
    }
}

Reported: HHH-6005.

like image 40
axtavt Avatar answered Sep 29 '22 12:09

axtavt