Is it possible for a JPA embeddable to contain Embeddable or Collection of Embeddables?
I wonder whether it is possible to have an ElementCollection of Embeddable inside another Embeddable ?
Here's an example of my Supplier entity which has a list of Addresses, which is of an embeddable type :
@Entity
public class Supplier extends BaseCommonEntity {
@Column(unique=true)
private String supplierCode;
private String supplierName;
@ElementCollection
private List<Address> addresses;
....
And here's my embeddable Address that co开发者_如何学Cntains a list of embeddable Phone
@Embeddable
public class Address {
private String address;
private String city;
private String country;
private String postcode;
@ElementCollection
private List<Phone> phones;
public List<Phone> getPhones() {
return phones;
}
public void setPhones(List<Phone> phones) {
this.phones = phones;
}
...
And here's the embeddable phone definition
@Embeddable
public class Phone {
private Long phoneCountryCode;
private Long phoneCityCode;
private Long phoneNo;
private Long faxCountryCode;
private Long faxCityCode;
private Long faxNo;
...
Im currently testing this with JPA 2 + Hibernate 3.6.x
Using the embeddable Phone inside the Address results in error in my test. Here's the partial debug messages from the most bottom :
DEBUG PropertyBinder - Building property country
DEBUG Ejb3Column - Binding column: Ejb3JoinColumn{logicalColumnName='null', referencedColumn='null', mappedBy=''}
DEBUG Ejb3Column - Binding column: Ejb3Column{table=org.hibernate.mapping.Table(Supplier_addresses), mappingColumn=phones, insertable=true, updatable=true, unique=false}
DEBUG Ejb3Column - Binding column: Ejb3Column{table=org.hibernate.mapping.Table(Supplier_addresses), mappingColumn=null, insertable=true, updatable=true, unique=false}
DEBUG Ejb3Column - Binding column: Ejb3Column{table=org.hibernate.mapping.Table(Supplier_addresses), mappingColumn=phones, insertable=true, updatable=true, unique=false}
DEBUG Ejb3Column - Binding column: Ejb3Column{table=org.hibernate.mapping.Table(Supplier_addresses), mappingColumn=phones_KEY, insertable=true, updatable=true, unique=false}
DEBUG Ejb3Column - Binding column: Ejb3JoinColumn{logicalColumnName='phones_KEY', referencedColumn='null', mappedBy='null'}
DEBUG Ejb3Column - Binding column: Ejb3JoinColumn{logicalColumnName='null', referencedColumn='null', mappedBy=''}
DEBUG Ejb3Column - Binding column: Ejb3JoinColumn{logicalColumnName='null', referencedColumn='null', mappedBy=''}
DEBUG CollectionBinder - Collection role: com.primetech.core.entity.Supplier.addresses.collection&&element.phones
DEBUG PropertyBinder - Building property phones
DEBUG Ejb3Column - Binding column: Ejb3Column{table=org.hibernate.mapping.Table(Supplier_addresses), mappingColumn=postcode, insertable=true, updatable=true, unique=false}
DEBUG PropertyBinder - binding property postcode with lazy=false
DEBUG SimpleValueBinder - building SimpleValue for postcode
DEBUG SimpleValueBinder - Setting SimpleValue typeName for postcode
DEBUG PropertyBinder - Building property postcode
DEBUG CollectionSecondPass - Mapped collection key: Supplier_id, element: address, city, country, postcode
DEBUG DefaultListableBeanFactory - Retrieved dependent beans for bean 'org.springframework.orm.jpa.vendor.HibernateJpaVendorAdapter#102799c': [entityManagerFactory]
INFO DefaultListableBeanFactory - Destroying singletons in org.springframework.beans.factory.support.DefaultListableBeanFactory@f6ac0b: defining beans [dataSource,entityManagerFactory,testEntities,org.springframework.context.annotation.internalConfigurationAnnotationProcessor,org.springframework.context.annotation.internalAutowiredAnnotationProcessor,org.springframework.context.annotation.internalRequiredAnnotationProcessor,org.springframework.context.annotation.internalCommonAnnotationProcessor,org.springframework.context.annotation.internalPersistenceAnnotationProcessor,transactionManager,org.springframework.aop.config.internalAutoProxyCreator,org.springframework.transaction.annotation.AnnotationTransactionAttributeSource#0,org.springframework.transaction.interceptor.TransactionInterceptor#0,org.springframework.transaction.config.internalTransactionAdvisor]; root of factory hierarchy
Exception in thread "main" org.springframework.beans.factory.BeanCreationException: Error creating bean with name 'entityManagerFactory' defined in class path resource [test.xml]: Invocation of init method failed; nested exception is java.util.ConcurrentModificationException
at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.initializeBean(AbstractAutowireCapableBeanFactory.java:1412)
at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.doCreateBean(AbstractAutowireCapableBeanFactory.java:519)
at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.createBean(AbstractAutowireCapableBeanFactory.java:456)
at org.springframework.beans.factory.support.AbstractBeanFactory$1.getObject(AbstractBeanFactory.java:291)
at org.springframework.beans.factory.support.DefaultSingletonBeanRegistry.getSingleton(DefaultSingletonBeanRegistry.java:222)
at org.springframework.beans.factory.support.AbstractBeanFactory.doGetBean(AbstractBeanFactory.java:288)
at org.springframework.beans.factory.support.AbstractBeanFactory.getBean(AbstractBeanFactory.java:190)
at org.springframework.beans.factory.support.DefaultListableBeanFactory.preInstantiateSingletons(DefaultListableBeanFactory.java:557)
at org.springframework.context.support.AbstractApplicationContext.finishBeanFactoryInitialization(AbstractApplicationContext.java:895)
at org.springframework.context.support.AbstractApplicationContext.refresh(AbstractApplicationContext.java:425)
at org.springframework.context.support.ClassPathXmlApplicationContext.<init>(ClassPathXmlApplicationContext.java:139)
at org.springframework.context.support.ClassPathXmlApplicationContext.<init>(ClassPathXmlApplicationContext.java:93)
at com.primetech.module.purchase.app.TestEntities.main(TestEntities.java:27)
Caused by: java.util.ConcurrentModificationException
at java.util.AbstractList$Itr.checkForComodification(AbstractList.java:372)
at java.util.AbstractList$Itr.remove(AbstractList.java:357)
at org.hibernate.cfg.Configuration.originalSecondPassCompile(Configuration.java:1687)
at org.hibernate.cfg.Configuration.secondPassCompile(Configuration.java:1393)
at org.hibernate.cfg.Configuration.buildMappings(Configuration.java:1345)
at org.hibernate.ejb.Ejb3Configuration.buildMappings(Ejb3Configuration.java:1477)
at org.hibernate.ejb.EventListenerConfigurator.configure(EventListenerConfigurator.java:193)
at org.hibernate.ejb.Ejb3Configuration.configure(Ejb3Configuration.java:1096)
at org.hibernate.ejb.Ejb3Configuration.configure(Ejb3Configuration.java:685)
at org.hibernate.ejb.HibernatePersistence.createContainerEntityManagerFactory(HibernatePersistence.java:73)
at org.springframework.orm.jpa.LocalContainerEntityManagerFactoryBean.createNativeEntityManagerFactory(LocalContainerEntityManagerFactoryBean.java:225)
at org.springframework.orm.jpa.AbstractEntityManagerFactoryBean.afterPropertiesSet(AbstractEntityManagerFactoryBean.java:308)
at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.invokeInitMethods(AbstractAutowireCapableBeanFactory.java:1469)
at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.initializeBean(AbstractAutowireCapableBeanFactory.java:1409)
... 12 more
Removing this part solves the problem
/**** REMOVE ALL OF THIS FROM THE CODE TO SOLVE THE PROBLEM ****/
@ElementCollection
private List<Phone> phones;
public List<Phone> getPhones() {
return phones;
}
public void setPhones(List<Phone> phones) {
this.phones = phones;
}
Please share your thoughts !
Thank you !
JPA 2 spec says no.
JSR-317
2.6 Collections of Embeddable Classes and Basic Types
An embeddable class (including an embeddable class within another embeddable class) that is contained within an element collection must not contain an element collection, nor may it contain a relationship to an entity other than a many-to-one or one-to-one relationship
精彩评论