Problem: How to use @Embedded multiple times in the same entity

Recently we had a requirement to use same @Embeddable class twice in same @Entity class.

Scenario goes like this

We have an Entity name Customer, in this entity here we used to use Postal Address Embeddable field type twice like homePostal and homePostal

@javax.persistence.Entity @Table class Customer { @Id @GeneratedValue private long id; @Column(name = "Customer_Name") private String name; private Date dob; @Embedded private PostalAddress homePostal; @Embedded private PostalAddress homePostal; } @Embeddable public class PostalAddress { private String prefix; @Embedded private PostalCode zipCode; } @Embeddable public class PostalCode { private String number; }

At runtime we will get below exception

Exception in thread "main" javax.persistence.PersistenceException: [PersistenceUnit:em1] Unable to build EntityManagerFactory at org.hibernate.ejb.Ejb3Confi guration.buildEntityManagerFactory (Ejb3Configuration.java:677) at com.cordys.em.HibernateEMUtil.main(HibernateEMUtil.java:48) Caused by: org.hibernate.MappingException: Repeated column in mapping for entity: com.cordys.em.domain.Customer column: prefix (should be mapped with insert="false" update="false")at org.hibernate.mapping.PersistentClass.checkColumnDuplication (PersistentClass.java:670)at org.hibernate.mapping.PersistentClass.checkPropertyColumnDuplication (PersistentClass.java:692) at org.hibernate.mapping.PersistentClass.checkPropertyColumnDuplication (PersistentClass.java:688) at org.hibernate.mapping.PersistentClass.checkColumnDuplication (PersistentClass.java:714)

Why we get this problem means because as we use same Embeddable field type, hibernate finds that as Embeddable type PostalAddress is not independent table, so Customer table will have duplicate columns, for examples prefix will become repeated column in Customer table.

Solution:

Alternative 1:

We have to override the attributes in Customer entity for at least one the Embeddable field as shown below

						
@javax.persistence.Entity @Table public class Customer { @Id @GeneratedValue private long id; @Column(name = "Customer_Name") private String name; private Date dob; @AttributeOverrides( { @AttributeOverride(name="prefix", column = @Column (name = "homePrefix")), @AttributeOverride(name="zipCode.number", column = @Column(name = "homePostal_zipcode_number")) }) @Embedded private PostalAddress homePostal; @AttributeOverrides( { @AttributeOverride(name="prefix", column = @Column (name ="offPrefix")), @AttributeOverride(name="zipCode.number", column = @Column(name = "offPostal_zipcode_number")) }) @Embedded private PostalAddress officePostal; }

Basically in this solution, as a developer we are explicitly overriding the column name of Embeddable type at its used i.e. where it is embedded

Alternative 2:

in persistent.xml add property

		
<property name="hibernate.ejb.naming_strategy" value="org.hibernate.cfg.DefaultComponentSafeNamingStrategy"/> it would take care of giving unique names for enbeddable field columns in target entity class. <properties> <property name="hibernate.dialect" value="org.hibernate.dialect.MySQLDialect" /> <property name="hibernate.hbm2ddl.auto" value="update" /> <property name="javax.persistence.validation.mode"> ddl, callback </property> <property name="hibernate.ejb.naming_strategy" value="org.hibernate.cfg.DefaultComponentSafeNamingStrategy"/> </properties>

In the DB Customer table will be created as shown below

Db customer table
Comments