【问题标题】:JPA AttributeOverride for Embeddable class with Entity type fields具有实体类型字段的可嵌入类的 JPA AttributeOverride
【发布时间】:2020-05-07 20:37:21
【问题描述】:

我有一个包含两个字段的可嵌入类。一个是枚举,另一个字段是实体类类型。

@Embeddable
public class EmbeddableClass {
    @OneToOne(cascade=CascadeType.ALL, fetch=FetchType.EAGER)
    @JoinColumn(name="myField", insertable = false, updatable = false)
    private EntityClass myField;

    @Enumerated(EnumType.STRING)
    @Column(name="enumValue", insertable=false, updatable=false)
    private EnumClass enumValue;

    protected EmbeddableClass() {}

    public EmbeddableClass(EntityClass myField, EnumClass enumValue) {
        this.myField = myField;
        this.enumValue = enumValue;
    }
}

我正在尝试将此类的对象嵌入到另一个类中。两个字段将属于这种类型,所以我必须使用@AttributeOverrides

@Entity
public class MyClass {
    @Column(name = "column_one")
    @AttributeOverrides({
            @AttributeOverride(name="enumValue", column= @Column(name="column_one_enum_value")),
            @AttributeOverride(name="myField", column= @Column(name="column_one_my_field"))
    })
    @Embedded
    private EmbeddableClass embeddableClass1;

    @Column(name = "column_two")
    @AttributeOverrides({
            @AttributeOverride(name="enumValue", column= @Column(name="column_two_enum_value")),
            @AttributeOverride(name="myField", column= @Column(name="column_two_my_field"))
    })
    @Embedded
    private EmbeddableClass embeddableClass2;

    // ...
}

在数据库中,我预计 MyClass 表将有 4 列以 @AttributeOverride 注释的第二个参数命名。但这不是我得到的。

枚举的两列是正确的。但是对于实体类字段,我没有得到两个单独的列。我只根据类型名称得到一列:entity_class。当我将MyClass 对象持久化到数据库中时,entity_class 列仍然为空,即使我持久化的对象确实具有myField 值。

有没有办法让我实现上面描述的 4 列,同时仍然保持类 Embeddable?

【问题讨论】:

    标签: java jpa spring-data-jpa


    【解决方案1】:

    您不必为 @Embedded 对象使用 @Column 注释,这些对象应在 MyClass 实体中分别替换为两列。

    更新 我仔细检查了documentation,似乎需要以下更新:

    1. 添加referencedColumnName = "id"以加入EmbeddableClass中的列定义
    @Embeddable
    public class EmbeddableClass {
        @OneToOne(cascade=CascadeType.ALL, fetch=FetchType.EAGER)
        @JoinColumn(name="myField", referencedColumnName = "id", insertable = false, updatable = false)
        private EntityClass myField;
    
        @Enumerated(EnumType.STRING)
        @Column(name="enumValue", insertable=false, updatable=false)
        private EnumClass enumValue;
    
        protected EmbeddableClass() {}
    
        public EmbeddableClass(EntityClass myField, EnumClass enumValue) {
            this.myField = myField;
            this.enumValue = enumValue;
        }
    }
    
    1. 使用对实例名称embeddableClass1/embeddableClass2 的引用更新@AssociationOverride/@AttributeOverride 中的name 属性:
    @AssociationOverrides({
        @AssociationOverride(name="embeddableClass1.myField", joinColumns = @JoinColumn(name="column_one_my_field")),
        @AssociationOverride(name="embeddableClass2.myField", joinColumns = @JoinColumn(name="column_two_my_field"))
    })
    @AttributeOverrides({
        @AttributeOverride(name="embeddableClass1.enumValue", column= @Column(name="column_one_enum_value")),
        @AttributeOverride(name="embeddableClass2.enumValue", column= @Column(name="column_two_enum_value"))
    })
    @Entity
    public class MyClass {
        @Embedded
        private EmbeddableClass embeddableClass1;
    
        @Embedded
        private EmbeddableClass embeddableClass2;
    
        // ...
    }
    
    1. (可选)如果您需要EntityClass 中的映射,您可以按照here 的说明添加它们:
    @Entity
    public class EntityClass {
        @Id
        private int id;
    
        @OneToOne(mappedBy = "embeddableClass1.myField")
        private MyClass myClass1;
    
        @OneToOne(mappedBy = "embeddableClass2.myField")
        private MyClass myClass2;
    }
    

    【讨论】:

    • 但它是 OneToOne 映射,而不是 OneToMany。如果我只是更改注释,则会出现错误(非法尝试将非集合映射为@OneToMany)。 OneToMany 会在没有 id 的可嵌入类中工作吗?它将如何映射到 db 表中?
    • 我不得不将关联/属性覆盖注释移动到类的顶部并将它们分组,就像您发布的休眠文档链接中一样。但它奏效了。我会相应地编辑你的答案。
    猜你喜欢
    • 2017-08-20
    • 2013-11-24
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2016-12-17
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多