Having a embeddable class MultiLanguageText:
@Embeddable
public class MultiLanguageText {
@Field
private String textDe;
@Field
private String textFr;
@Field
private String textIt;
//...
}
And another class that uses this class twice:
@Entity(name = "T_AnotherClass")
public class AnotherClass{
@Id
@GeneratedValue
private long key;
@Embedded
private MultiLanguageText name;
@Embedded
private MultiLanguageText description;
//...
}
The fields got translated perfectly fine into "name_textDe", "description_textDe", "name_textFr" and so on with the spring version 1.2.7.RELEASE.
However to store LocalDate's I wanted to upgrade to Hibernate 5. I followed the process described here: https://github.com/spring-projects/spring-boot/issues/2763#issuecomment-154419889
The process worked fine but the translation of the embedded fields stoped working *. I tried different implicit_naming_strategy and physical_naming_strategy, but non of them worked.
If I annotate the fields as follows it does work, but the process is somewhat cumbersome:
@Embedded
@AttributeOverrides({
@AttributeOverride(name = "textDe", column = @Column(name = "name_textDe", length = MultiLanguageText.MAX_TEXT_LENGTH)),
@AttributeOverride(name = "textFr", column = @Column(name = "name_textFr", length = MultiLanguageText.MAX_TEXT_LENGTH)),
@AttributeOverride(name = "textIt", column = @Column(name = "name_textIt", length = MultiLanguageText.MAX_TEXT_LENGTH)),
})
private MultiLanguageText name;
*Not working does mean I get an exception something along the lines of (as now the field gets mapped without the fieldname prefix and therefore the field exist twice):
Caused by: org.hibernate.MappingException: Repeated column in mapping for entity: AnotherClass column: textDe (should be mapped with insert="false" update="false")
at org.hibernate.mapping.PersistentClass.checkColumnDuplication(PersistentClass.java:764)
at org.hibernate.mapping.PersistentClass.checkPropertyColumnDuplication(PersistentClass.java:782)
at org.hibernate.mapping.PersistentClass.checkPropertyColumnDuplication(PersistentClass.java:778)
at org.hibernate.mapping.PersistentClass.checkColumnDuplication(PersistentClass.java:804)
at org.hibernate.mapping.PersistentClass.validate(PersistentClass.java:539)
at org.hibernate.mapping.RootClass.validate(RootClass.java:265)
at org.hibernate.boot.internal.MetadataImpl.validate(MetadataImpl.java:329)
at org.hibernate.boot.internal.SessionFactoryBuilderImpl.build(SessionFactoryBuilderImpl.java:443)
at org.hibernate.jpa.boot.internal.EntityManagerFactoryBuilderImpl.build(EntityManagerFactoryBuilderImpl.java:879)
... 48 more
To fix this in Spring Boot 1.4, add this to your application.yaml
:
spring.jpa.hibernate.naming.implicit-strategy: org.hibernate.boot.model.naming.ImplicitNamingStrategyComponentPathImpl
From the javadocs:
An ImplicitNamingStrategy implementation which uses full composite paths extracted from AttributePath, as opposed to just the terminal property part. Mainly a port of the older DefaultComponentSafeNamingStrategy class implementing the no longer supported NamingStrategy contract.
Hibernate official documentation says:
If you want to have the same embeddable object type twice in the same entity, the column name defaulting will not work as several embedded objects would share the same set of columns. In plain JPA, you need to override at least one set of columns. Hibernate, however, allows you to enhance the default naming mechanism through the NamingStrategy interface. You can write a strategy that prevent name clashing in such a situation. DefaultComponentSafeNamingStrategy is an example of this.
Consequently, if you wish to have full JPA compliance, stick with your current implementation.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With