2011-03-11 11 views
10

Estoy usando Hibernate 3.5.6 como mi implementación de JPA 2.0. Estoy tratando de construir un @ElementCollection dentro de mi entidad (muchos campos omitidos):Cómo compilar ElementCollection de tipo Embeddable?

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

que he hecho este trabajo con bastante facilidad cuando la colección contiene un tipo básico, pero mi ContactDetails es una clase @Embeddable:

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

cuando corro dejar que Hibernate generar el DDL, recibo errores como este:

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 

¿hay una manera de persuadir a Hibernate Gen ¿Cuál es el nombre de columna válido en la tabla para la clase de colección? Idealmente, una forma que no viole el principio No repetir uno mismo al especificar cada nombre de columna individual.

Respuesta

12

Es un error en Hibernate causado por la incompatibilidad de DefaultComponentSafeNamingStrategy con @ElementCollection detalles de implementación.

.collection&&element. es un marcador de posición interno que debe eliminarse antes de usar el nombre de propiedad como nombre de columna. Otras estrategias de nomenclatura lo eliminan eficazmente utilizando solo la parte del nombre de la propiedad después de la última ., mientras que DefaultComponentSafeNamingStrategy reemplaza a . con _ s pero no elimina el marcador de posición.

Si realmente necesita DefaultComponentSafeNamingStrategy, aquí hay una solución:

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

del informe: HHH-6005.

+0

Eso era exactamente, gracias. –

+0

De acuerdo con el rastreador de errores esto está arreglado en Hibernate 5. –

+0

Me llevó varias horas encontrarlo. El mensaje de error estaba bastante bien oculto registros ddl completos. ¡Gracias! – Mateusz

-6

Acabamos de lanzar Batoo JPA, la nueva implementación de Java Persistence API spec 1.0 & 2.0, con el rendimiento siendo el foco principal. Es más de 15 veces más rápido que Hibernate. El sitio web del proyecto es http://batoo.jp

He intentado su caso contra Batoo JPA y funciona perfectamente. También puede consultar las pruebas unitarias de @ElementCollection en BAtoo JPA here.

Atentamente.

2

solución alternativa usando @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", [email protected](name="personId")), 
    @AttributeOverride(name="placeRoleId", [email protected](name="placeRoleId")) 
}) 
private Set<PlaceMember> members = new HashSet<PlaceMember>(); 
Cuestiones relacionadas