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.
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.
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>();
We have just released Batoo JPA, the new implementation of Java Persistence API spec 1.0 & 2.0, with the performance being the main focus. It is over 15x times faster then Hibernate. The project website is http://batoo.jp
I have tried your case against Batoo JPA and it runs just fine. You may also check the unit tests for @ElementCollection in BAtoo JPA here.
Regards.
精彩评论