Hibernate Fix DuplicateMappingException
1. Introduction
To fix DuplicateMappingException requires that a column only maps to a single field. The org.hibernate.DuplicateMappingException is a runtime exception and is raised whenever a duplicate for a certain type occurs. In this example, I will create a Spring Data JPA project to demonstrate five entities that throw the duplicate column exception and how to fix it.
- Duplicate columns mapping within an entity.
- Duplicate columns mapping with
@JoinColumn
. - Duplicate columns mapping with
@Embedded
. - Duplicate columns mapping with
@MappedSuperclass
. - Duplicate columns with two entities mapped to the same table.
2. Setup
In this step, I will create a gradle project with H2, Spring Data JPA, and Lombok libraries.
build.gradle
plugins { id 'java' id 'org.springframework.boot' version '3.5.0' id 'io.spring.dependency-management' version '1.1.7' } group = 'org.zheng.demo' version = '0.0.1-SNAPSHOT' java { toolchain { languageVersion = JavaLanguageVersion.of(17) } } configurations { compileOnly { extendsFrom annotationProcessor } } repositories { mavenCentral() } dependencies { implementation 'org.springframework.boot:spring-boot-starter-data-jpa' compileOnly 'org.projectlombok:lombok' runtimeOnly 'com.h2database:h2' annotationProcessor 'org.projectlombok:lombok' testImplementation 'org.springframework.boot:spring-boot-starter-test' testRuntimeOnly 'org.junit.platform:junit-platform-launcher' } tasks.named('test') { useJUnitPlatform() }
2.1 Application.properties
In this step, I will update the application.properties
to configure the log levels.
application.properties
spring.application.name=HibernateMappingExceptionDemo spring.jpa.show-sql=true spring.jpa.properties.hibernate.format_sql=true logging.level.org.hibernate=DEBUG logging.level.org.hibernate.orm.mapping=TRACE logging.level.org.springframework.context=DEBUG logging.level.org.springframework.boot.autoconfigure.orm.jpa=DEBUG
2.2 Address
In this step, I will create the Address.java
as an embeddable object.
Address.java
package org.jcg.zheng.entity; import jakarta.persistence.Embeddable; import lombok.Data; @Embeddable @Data public class Address { private String line1; private String line2; private String city; private String state; private String zipCode; }
2.3 BaseEntity
In this step, I will create the BaseEntity.java
as a base entity.
BaseEntity.java
package org.jcg.zheng.entity; import java.time.LocalDateTime; import jakarta.persistence.Column; import jakarta.persistence.MappedSuperclass; @MappedSuperclass public class BaseEntity { @Column(name="created_at") private LocalDateTime createdAt; }
3. Duplicate Column Mapping
In this step, I will demonstrate that Spring Data JPA throws a MappingException
when a column is mapped to multiple fields of an entity. We can fix it by removing the extra fields or remapping to a different column.
3.1 Duplicate Column Mapping
In this step, I will create a DemoEntity.java
that annotates with @Table
and maps to the T_DEMO
table. It maps both firstName
and lastName
to the same “name
” column, so it triggers the HibernateMappingException
during the Spring context creation.
DemoEntity
package org.jcg.zheng.entity; import jakarta.persistence.Column; import jakarta.persistence.Entity; import jakarta.persistence.GeneratedValue; import jakarta.persistence.GenerationType; import jakarta.persistence.Id; import jakarta.persistence.Table; import lombok.Data; @Entity @Table(name = "T_DEMO") @Data public class DemoEntity { @Id @GeneratedValue(strategy = GenerationType.IDENTITY) private Integer id; private Integer age; @Column(name = "name") private String firstName; @Column(name = "name") private String lastName; }
- Line 22, 25: two fields map to the same column:
name
and cause theDuplicateMappingException
. We can remove or remap to a different column.
3.2 DemoEntityRepo
In this step, I will create a DemoEntityRepo.java
that annotates with @Repository
and extends from JpaRepository
.
DemoEntityRepo.java
package org.jcg.zheng.repo; import org.jcg.zheng.entity.DemoEntity; import org.springframework.data.jpa.repository.JpaRepository; import org.springframework.stereotype.Repository; @Repository public interface DemoEntityRepo extends JpaRepository<DemoEntity, Integer> { }
3.3 DemoEntityRepoTest
In this step, I will create a DemoEntityRepoTest.java
that annotates with @SpringBootTest
and save a DemoEntity
.
DemoEntityRepoTest.java
package org.jcg.zheng.repo; import static org.junit.jupiter.api.Assertions.assertNotNull; import static org.junit.jupiter.api.Assertions.assertNull; import org.jcg.zheng.entity.DemoEntity; import org.junit.jupiter.api.Test; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.boot.test.context.SpringBootTest; @SpringBootTest class DemoEntityRepoTest { @Autowired private DemoEntityRepo testRepo; private DemoEntity demoEntity = new DemoEntity(); @Test void testSave() { assertNull(demoEntity.getId()); demoEntity.setFirstName("Mary"); testRepo.save(demoEntity); assertNotNull(demoEntity.getId()); } }
3.4 Caught DuplicateMappingException
In this step, I will execute DemoEntityRepoTest.java
and capture the exception details.
DemoEntityRepoTest Output
Caused by: org.hibernate.MappingException: Column 'name' is duplicated in mapping for entity 'org.jcg.zheng.entity.DemoEntity' (use '@Column(insertable=false, updatable=false)' when mapping multiple properties to the same column)
- The error message states that the
MappingException
is caused by"Column 'name' is duplicated in mapping for entity 'org.jcg.zheng.entity.DemoEntity'"
. We can fix it by configuringinsertable
andupdable
attributes with thefalse
value. The common solution is to remove or remap the duplicate fields outlined in step 3.1.
3.5 Fix DuplicateMappingException
In this step, I will update DemoEntity.java
and correct the “name
” column to map to “firstName
“. After that, run the same DemoEntityRepoTest
and confirm the test passed.
DemoEntityRepoTest Output
2025-06-14T14:07:36.958-05:00 DEBUG 27080 --- [HibernateMappingExceptionDemo] [ main] org.hibernate.SQL : insert into t_demo (age, first_name, name, id) values (?, ?, ?, default) Hibernate: insert into t_demo (age, first_name, name, id) values (?, ?, ?, default) 2025
4. Mapping a Column to Many Fields Within @Embedded
This step is similar to step 3. The difference is the mapped field is a part of @Embedded
object.
4.1 Map the Same Column Many Times with @Embedded Object
In this step, I will create a DemoEmbedEntity.java
that annotates with @Table
and maps to the T_DEMO_EMBED
table. The state
column is mapped to both address
and state
, so it triggers the HibernateMappingException
during the Spring context creation.
DemoEntity
package org.jcg.zheng.entity; import jakarta.persistence.Column; import jakarta.persistence.Embedded; import jakarta.persistence.Entity; import jakarta.persistence.GeneratedValue; import jakarta.persistence.GenerationType; import jakarta.persistence.Id; import jakarta.persistence.Table; import lombok.Data; @Entity @Table(name = "T_DEMO_EMBED") @Data public class DemoEmbedEntity { @Id @GeneratedValue(strategy = GenerationType.IDENTITY) private Integer id; private String name; @Embedded private Address address; /* MappingException: Column 'state' is duplicated in mapping for entity */ @Column(name = "state") private String state; }
- Line 24, 27: the
state
is mapped twice, one is defined inAddress
outlined in step 2.2, the other is thestate
field.
4.2 DemoEmbedEntityRepo
In this step, I will create a DemoEmbedEntityRepo.java
that annotates with @Repository
and extends from JpaRepository
.
DemoEmbedEntityRepo.java
package org.jcg.zheng.repo; import org.jcg.zheng.entity.DemoEmbedEntity; import org.springframework.data.jpa.repository.JpaRepository; import org.springframework.stereotype.Repository; @Repository public interface DemoEmbedEntityRepo extends JpaRepository<DemoEmbedEntity, Integer> { }
4.3 DemoEmbedEntityRepoTest
In this step, I will create a DemoEmbedEntityRepoTest.java
that annotates with @SpringBootTest
and save a DemoEmbedEntity
.
DemoEmbedEntityRepoTest.java
package org.jcg.zheng.repo; import static org.junit.jupiter.api.Assertions.assertNotNull; import static org.junit.jupiter.api.Assertions.assertNull; import org.jcg.zheng.entity.DemoEmbedEntity; import org.junit.jupiter.api.Test; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.boot.test.context.SpringBootTest; @SpringBootTest class DemoEmbedEntityRepoTest { @Autowired private DemoEmbedEntityRepo testRepo; private DemoEmbedEntity demoEntity = new DemoEmbedEntity(); @Test void testSave() { assertNull(demoEntity.getId()); demoEntity.setName("Mary"); testRepo.save(demoEntity); assertNotNull(demoEntity.getId()); } }
4.4 Caught DuplicateMappingException
In this step, I will execute DemoEmbedEntityRepoTest.java
and capture the exception details.
DemoEmbedEntityRepoTest Output
Caused by: org.hibernate.MappingException: Column 'state' is duplicated in mapping for entity 'org.jcg.zheng.entity.DemoEmbedEntity' (use '@Column(insertable=false, updatable=false)' when mapping multiple properties to the same column)
4.5 Fix DuplicateMappingException
In this step, I will update DemoEmbedEntity.java
and remove the “state
“. After that, run the same DemoEmbedEntityRepoTest
and confirm the test passed.
DemoEmbedEntityRepoTest Output
2025-06-14T14:22:27.142-05:00 DEBUG 15112 --- [HibernateMappingExceptionDemo] [ main] org.hibernate.SQL : insert into t_demo_embed (city, line1, line2, state, zip_code, name, id) values (?, ?, ?, ?, ?, ?, default) Hibernate: insert into t_demo_embed (city, line1, line2, state, zip_code, name, id) values (?, ?, ?, ?, ?, ?, default)
5. JoinColumn With Same Name
5.1 Map the Same Column via @JoinColumn
In this step, I will create a DemoJoinEntity.java
that annotates with @Table
and maps to the T_DEMO_JOIN
table. The foreign key “demo_id
” column is mapped to both demo
and demo_id
, so it triggers the HibernateMappingException
during the Spring context creation.
DemoJoinEntity
package org.jcg.zheng.entity; import jakarta.persistence.CascadeType; import jakarta.persistence.Entity; import jakarta.persistence.GeneratedValue; import jakarta.persistence.GenerationType; import jakarta.persistence.Id; import jakarta.persistence.JoinColumn; import jakarta.persistence.OneToOne; import jakarta.persistence.Table; import lombok.Data; @Entity @Table(name = "T_DEMO_JOIN") @Data public class DemoJoinEntity { @Id @GeneratedValue(strategy = GenerationType.IDENTITY) private Integer id; private String name; @OneToOne(cascade = CascadeType.PERSIST) @JoinColumn(name = "demo_id") private DemoEntity demo; /* MappingException Column 'demo_id' is duplicated in mapping for entity */ @JoinColumn(name = "demo_id") private Integer demo_id; }
- Line 25, 29: the “
demo_id
” column is mapped to two fields and triggers theDuplicateMappingException
.
5.2 DemoJoinEntityRepo
In this step, I will create a DemoJoinEntityRepo.java
that annotates with @Repository
and extends from JpaRepository
.
DemoJoinEntityRepo.java
package org.jcg.zheng.repo; import org.jcg.zheng.entity.DemoJoinEntity; import org.springframework.data.jpa.repository.JpaRepository; import org.springframework.stereotype.Repository; @Repository public interface DemoJoinEntityRepo extends JpaRepository<DemoJoinEntity, Integer> { }
5.3 DemoJoinEntityRepoTest
In this step, I will create a DemoJoinEntityRepoTest.java
that annotates with @SpringBootTest
and save a DemoEntity
.
DemoJoinEntityRepoTest.java
package org.jcg.zheng.repo; import static org.junit.jupiter.api.Assertions.assertNotNull; import static org.junit.jupiter.api.Assertions.assertNull; import org.jcg.zheng.entity.DemoJoinEntity; import org.junit.jupiter.api.Test; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.boot.test.context.SpringBootTest; @SpringBootTest class DemoJoinEntityRepoTest { @Autowired private DemoJoinEntityRepo testRepo; private DemoJoinEntity demoEntity = new DemoJoinEntity(); @Test void testSave() { assertNull(demoEntity.getId()); demoEntity.setName("Mary"); testRepo.save(demoEntity); assertNotNull(demoEntity.getId()); } }
5.4 Caught DuplicateMappingException
In this step, I will execute DemoJoinEntityRepoTest.java
and capture the exception details.
DemoJoinEntityRepoTest Output
Caused by: org.hibernate.MappingException: Column 'demo_id' is duplicated in mapping for entity 'org.jcg.zheng.entity.DemoJoinEntity' (use '@Column(insertable=false, updatable=false)' when mapping multiple properties to the same column)
5.5 Fix DuplicateMappingException
In this step, I will update DemoJoinEntity.java
and remove the “demo_id
“. After that, run the same DemoJoinEntityRepoTest
and confirm the test passed.
DemoJoinEntityRepoTest Output
2025-06-14T14:33:18.991-05:00 DEBUG 11332 --- [HibernateMappingExceptionDemo] [ main] org.hibernate.SQL : insert into t_demo_join (demo_id, name, id) values (?, ?, default) Hibernate: insert into t_demo_join (demo_id, name, id) values (?, ?, default)
6. Inheritance Duplicate Mapping
6.1 The Same Column Map to Both Parent and Child Entities
In this step, I will create a DemoChildEntity.java
that annotates with @Table
and maps to the T_DEMO_CHILD
table. The created_at
column is mapped in both BaseEntity
and DemoChildEntity
, so it triggers the HibernateMappingException
during the Spring context creation.
DemoChildEntity
package org.jcg.zheng.entity; import java.time.LocalDateTime; import jakarta.persistence.Column; import jakarta.persistence.Entity; import jakarta.persistence.GeneratedValue; import jakarta.persistence.GenerationType; import jakarta.persistence.Id; import jakarta.persistence.Table; import lombok.Data; @Entity @Table(name = "T_DEMO_CHILD") @Data public class DemoChildEntity extends BaseEntity { @Id @GeneratedValue(strategy = GenerationType.IDENTITY) private Integer id; private String name; /* * MappingException: Column 'created_at' is duplicated in mapping for entity */ @Column(name="created_at") private LocalDateTime createdDateTime; }
- Line 27: the “
created_at
” column is mapped inBaseEntity
outlined in step 2.3.
6.2 DemoChildEntityRepo
In this step, I will create a DemoChildEntityRepo.java
that annotates with @Repository
and extends from JpaRepository
.
DemoChildEntityRepo.java
package org.jcg.zheng.repo; import org.jcg.zheng.entity.DemoChildEntity; import org.springframework.data.jpa.repository.JpaRepository; import org.springframework.stereotype.Repository; @Repository public interface DemoChildEntityRepo extends JpaRepository<DemoChildEntity, Integer> { }
6.3 DemoChildEntityRepoTest
In this step, I will create a DemoChildEntityRepoTest.java
that annotates with @SpringBootTest
and save a DemoEntity
.
DemoChildEntityRepoTest.java
package org.jcg.zheng.repo; import static org.junit.jupiter.api.Assertions.assertNotNull; import static org.junit.jupiter.api.Assertions.assertNull; import org.jcg.zheng.entity.DemoChildEntity; import org.junit.jupiter.api.Test; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.boot.test.context.SpringBootTest; @SpringBootTest class DemoChildEntityRepoTest { @Autowired private DemoChildEntityRepo testRepo; private DemoChildEntity demoEntity = new DemoChildEntity(); @Test void testSave() { assertNull(demoEntity.getId()); demoEntity.setName("Mary"); testRepo.save(demoEntity); assertNotNull(demoEntity.getId()); } }
6.4 Caught DuplicateMappingException
In this step, I will execute DemoChildEntityRepoTest.java
and capture the exception details.
DemoChildEntityRepoTest Output
Caused by: org.hibernate.MappingException: Column 'created_at' is duplicated in mapping for entity 'org.jcg.zheng.entity.DemoChildEntity' (use '@Column(insertable=false, updatable=false)' when mapping multiple properties to the same column)
6.5 Fix DuplicateMappingException
In this step, I will update DemoChildEntity.java
and remove “createdDateTime
“. After that, run the same DemoChildEntityRepoTest
and confirm the test passed.
DemoEntityRepoTest Output
2025-06-14T14:55:21.421-05:00 DEBUG 22324 --- [HibernateMappingExceptionDemo] [ main] org.hibernate.SQL : insert into t_demo_child (created_at, name, id) values (?, ?, default) Hibernate: insert into t_demo_child (created_at, name, id) values (?, ?, default)
7. Mapping Table with Many Entities
When more than one @Entity
classes map to the same table and there is conflicting column mapping, then the duplicate mapping exception is thrown.
7.1 Map Another Entity for T_DEMO table
In this step, I will create a DemoDuplicateEntity.java
that annotates with @Table
and maps to the T_DEMO
table as the DemoEntity.java
outlined in step 3. It maps both age
and name
to the same “age
” column, so it triggers the HibernateMappingException
during the Spring context creation.
DemoDuplicateEntity
package org.jcg.zheng.entity; import jakarta.persistence.Column; import jakarta.persistence.Entity; import jakarta.persistence.GeneratedValue; import jakarta.persistence.GenerationType; import jakarta.persistence.Id; import jakarta.persistence.Table; import lombok.Data; @Entity @Table(name = "T_DEMO") @Data public class DemoDuplicateEntity { @Id @GeneratedValue(strategy = GenerationType.IDENTITY) private Integer id; private Integer age; private String firstName; // MappingException: Column 'age' is duplicated in mapping for entity @Column(name="age") private String name; }
- Line 20, 25: both fields map to the same “age” column. Need to remove one of them.
7.2 DemoDuplicateEntityRepo
In this step, I will create a DemoDuplicateEntityRepo.java
that annotates with @Repository
and extends from JpaRepository
.
DemoDuplicateEntityRepo.java
package org.jcg.zheng.repo; import org.jcg.zheng.entity.DemoDuplicateEntity; import org.springframework.data.jpa.repository.JpaRepository; import org.springframework.stereotype.Repository; @Repository public interface DemoDuplicateEntityRepo extends JpaRepository<DemoDuplicateEntity, Integer> { }
7.3 DemoDuplicateEntityRepoTest
In this step, I will create a DemoEntityRepoTest.java
that annotates with @SpringBootTest
and save a DemoEntity
.
DemoEntityRepoTest.java
package org.jcg.zheng.repo; import static org.junit.jupiter.api.Assertions.assertNotNull; import static org.junit.jupiter.api.Assertions.assertNull; import org.jcg.zheng.entity.DemoDuplicateEntity; import org.junit.jupiter.api.Test; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.boot.test.context.SpringBootTest; @SpringBootTest class DemoDuplicateEntityRepoTest { @Autowired private DemoDuplicateEntityRepo testRepo; private DemoDuplicateEntity demoEntity = new DemoDuplicateEntity(); @Test void testSave() { assertNull(demoEntity.getId()); demoEntity.setName("Mary"); testRepo.save(demoEntity); assertNotNull(demoEntity.getId()); } }
7.4 Caught DuplicateMappingException
In this step, I will execute DemoDuplicateEntityRepoTest.java
and capture the exception details.
DemoEntityRepoTest Output
Caused by: org.hibernate.MappingException: Column 'age' is duplicated in mapping for entity 'org.jcg.zheng.entity.DemoDuplicateEntity' (use '@Column(insertable=false, updatable=false)' when mapping multiple properties to the same column)
7.5 Fix DuplicateMappingException
In this step, I will update DemoDuplicateEntity.java
and change the “age
” column to only map to “age
“. After that, run the same DemoDuplicateEntityRepoTest
and confirm the test passed.
DemoDuplicateEntityRepoTest Output
2025-06-14T18:12:07.654-05:00 DEBUG 29732 --- [HibernateMappingExceptionDemo] [ main] org.hibernate.SQL : insert into t_demo (age, first_name, name, id) values (?, ?, ?, default) Hibernate: insert into t_demo (age, first_name, name, id) values (?, ?, ?, default)
Run the Junit tests and capture the results after removing duplicate columns.
8. Conclusion
In this example, I showed that Hibernate MappingException
is thrown during the Spring context initialization when there is a column mapped to many fields in an entity. The duplicate fields can be found in the entity class, base class, embed object, or joined column. To fix it, we can remove the duplicate field or re-map it to a different column based on the detail message of the MappingException
.
9. Download
This was an example of a Spring boot JPA gradle project that demonstrated a fix for DuplicateMappingException
.
You can download the full source code of this example here: Hibernate Fix DuplicateMappingException