【问题标题】:Embedded field does not work after upgrading to Hibernate 5.0.6.Final in Spring Boot 1.3.1.RELEASE在 Spring Boot 1.3.1.RELEASE 中升级到 Hibernate 5.0.6.Final 后嵌入字段不起作用
【发布时间】:2016-01-04 16:03:15
【问题描述】:

拥有一个可嵌入类 MultiLanguageText:

@Embeddable
public class MultiLanguageText {
@Field
private String textDe;
@Field
private String textFr;
@Field
private String textIt;
//...
}

另一个使用这个类两次的类:

@Entity(name = "T_AnotherClass")
public class AnotherClass{
@Id
@GeneratedValue
private long key;
@Embedded
private MultiLanguageText name;
@Embedded
private MultiLanguageText description;
//...
}

这些字段在春季版本 1.2.7.RELEASE 中被完美地翻译成“name_textDe”、“description_textDe”、“name_textFr”等。

但是要存储 LocalDate 的,我想升级到 Hibernate 5。我按照此处描述的过程进行操作:https://github.com/spring-projects/spring-boot/issues/2763#issuecomment-154419889

该过程运行良好,但嵌入字段的翻译停止工作 *.我尝试了不同的implicit_naming_strategy 和physical_naming_strategy,但都没有奏效。

如果我将字段注释如下,它确实有效,但过程有点麻烦:

@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;

*不工作确实意味着我得到了一个异常(因为现在该字段被映射而没有字段名前缀,因此该字段存在两次):

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

【问题讨论】:

    标签: java hibernate spring-boot


    【解决方案1】:

    要在 Spring Boot 1.4 中解决此问题,请将其添加到您的 application.yaml

    spring.jpa.hibernate.naming.implicit-strategy: org.hibernate.boot.model.naming.ImplicitNamingStrategyComponentPathImpl
    

    来自javadocs

    使用完全复合的 ImplicitNamingStrategy 实现 从 AttributePath 提取的路径,而不仅仅是终端 财产部分。主要是老港口 DefaultComponentSafeNamingStrategy 类实现不再 支持 NamingStrategy 合约。

    【讨论】:

    • 当你这样做时,你不能在任何地方使用@CollectionTable,因为字段被映射为parent_field_collection&&element_child_field。集合&&元素部分来自命名策略导致sql语法错误
    【解决方案2】:

    Hibernate 官方文档说:

    如果您想在同一个文件中拥有两次相同的可嵌入对象类型 实体,列名默认不会像几个嵌入的一样工作 对象将共享同一组列。在普通的 JPA 中,您需要 覆盖至少一组列。然而,Hibernate 允许您 通过 NamingStrategy 增强默认命名机制 界面。您可以编写一个防止名称冲突的策略 一种情况。 DefaultComponentSafeNamingStrategy 就是一个例子。

    因此,如果您希望完全符合 JPA,请坚持当前的实施。

    【讨论】:

      猜你喜欢
      • 2021-12-22
      • 2018-10-22
      • 1970-01-01
      • 2023-04-07
      • 2019-04-16
      • 2021-09-15
      • 2021-09-06
      • 1970-01-01
      • 2018-05-30
      相关资源
      最近更新 更多