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:
nameand 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
MappingExceptionis caused by"Column 'name' is duplicated in mapping for entity 'org.jcg.zheng.entity.DemoEntity'". We can fix it by configuringinsertableandupdableattributes with thefalsevalue. 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)
20254. 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
stateis mapped twice, one is defined inAddressoutlined in step 2.2, the other is thestatefield.
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 inBaseEntityoutlined 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


