Using @AttributeOverride To Resolve Conflicts

Overview

When working with spring data jpa, you probably come across issues like this: You have an entity with an @Embedded attribute. The @Embeddable class has the one property that has the same name as one of your entities’.

You got this error when running the program:

Caused by: org.hibernate.MappingException: Column 'name' is duplicated in mapping for entity 'com.datmt.springdatapostgres.model.Car' (use '@Column(insertable=false, updatable=false)' when mapping multiple properties to the same column)
        at org.hibernate.mapping.Value.checkColumnDuplication(Value.java:197)
        at org.hibernate.mapping.MappingHelper.checkPropertyColumnDuplication(MappingHelper.java:249)
        at org.hibernate.mapping.PersistentClass.checkColumnDuplication(PersistentClass.java:938)
        at org.hibernate.mapping.PersistentClass.validate(PersistentClass.java:678)
        at org.hibernate.mapping.RootClass.validate(RootClass.java:273)w

What do you do?

Why Do you have naming conflict with Embedded property

When you use @Embedded type in your entity, the data for the embedded property is store on the same table as your entity. Thus, cases like this:

@Entity
public class Car extends Thing {

    private String name;
    @Embedded
    private Engine engine;
}

@Embeddable
public class Engine {
    private String name;
    private int power;
}

Would result in a naming conflict.

Fix duplicate properties’ name with Embedded type

The fix is quite simple. You can use @AttributeOverride quite effectively. The code above could be rewritten as such:

@Entity
public class Car extends Thing {

    private String name;
    @Embedded
    @AttributeOverride(name = "name", column = @Column(name = "engine_name"))
    private Engine engine;
}

Now, I have no problem running this code:

    @Test
    @DisplayName("Test embeddable")
    void testEmbeddable() {
        var engine = new Engine("V8", 1000);
        var car = new Car("BMW", engine);
        commonRepository.save(car);
    }
Using attributeOverride to resolve naming conflicts.

In case you have multiple naming conflicts, you can use @AttributeOverrides instead.

Imagine both Car and Engine have installedDate and maintenanceDate, the following code would resolve the issue:

@Embedded
@AttributeOverrides({
    @AttributeOverride(name = "installedDate", column = @Column(name = "engine_installed_date")),
    @AttributeOverride(name = "maintenanceDate", column = @Column(name = "engine_maintenance_date"))
})
private Engine engine;

Conclusion

In this post, I’ve shown you how to resolve naming conflicts when using @Embedded/@Embeddable in spring data jpa.

Leave a Comment