在 Hibernate 中是否可以使用可选的 ElementCollections

问题描述

我注意到我的一个应用程序中出现了一些奇怪的行为。我在两个类 Frame 和 Brand 之间存在多对一关系。就数据库而言,关系是单向的。表中的每个 Frame 都有一个 brand_id 列,但 Brand 没有任何反向指向的列。到目前为止一切都很好,但在实际代码中,我有时需要获取有关与特定品牌相关联的所有框架的信息。为方便起见,我向 Brand 类添加一个字段,该字段包含框架 ID 的集合,并使用 @ElementCollection 和 @CollectionTable 对其进行注释。

这就是事情变得有点时髦的地方。 Frame 类是使用单表继承的层次结构的一部分。并非所有映射到该表的类都有品牌,因此brand_id 列必须可以为空。到目前为止,我已经能够确定,对于用@ElementCollection 注释的关系,Hibernate 强制“可空”为假。似乎没有任何文档解释原因。相关代码可以在 hibernate-core-5.3.13.Final.jar 的 'org.hibernate.cfg.Ejb3JoinColumn.buildJoinTableJoinColumns()' 中找到,但它说的是

currentJoinColumn.setNullable(false); //我打破了规范,但它是 永远的

有没有办法在 Hibernate 中覆盖这个限制?如果没有,是否有其他方法可以在不使用 @ElementCollection 的情况下做我想做的事?

我的代码

@Entity(name = "Frame")
@discriminatorValue("FRAME")
public class Frame extends Product
{
    @ManyToOne(optional=true)
    @JoinColumn(name = "brand_id")
    @IndexedEmbedded
    protected Brand brand;

    public Brand getBrand()
    {
        return brand;
    }
}

@Entity(name = "Brand")
@Table(name = "brands")
public class Brand extends Entity
{
    @ElementCollection
    @CollectionTable(name = "products",joinColumns = @JoinColumn(name = "brand_id"))
    @Column(name = "id")
    protected Set<BigInteger> frameIds;

    public Set<BigInteger> getFrameIds()
    {
        return frameIds;
    }

    public void setFrameIds(Set<BigInteger> frameIds)
    {
        this.frameIds = frameIds;
    }
}

public class Foo extends Entity
{
    @ManyToOne
    @JoinColumn(name = "brand_id")
    protected Brand brand;

    @ManyToMany(fetch = FetchType.LAZY,cascade = CascadeType.ALL)
    @JoinTable(name = "frames_to_features",inverseJoinColumns = {
        @JoinColumn(name = "frame_id",referencedColumnName = "id") },joinColumns = {
                @JoinColumn(name = "feature_id",referencedColumnName = "id") })
    protected Set<Frame> frames;

    public List<BigInteger> getExcludedFrameIds()
    {
        List<BigInteger> brandFrames = new ArrayList<BigInteger>();
        if (getBrand() != null)
        {
            brandFrames.addAll(getBrand().getFrameIds());
            Set<BigInteger> localFrames = getFrameIds();
            if (localFrames != null)
            {
                brandFrames.removeAll(localFrames);
            }
        }
        return brandFrames;
    }
}

解决方法

暂无找到可以解决该程序问题的有效方法,小编努力寻找整理中!

如果你已经找到好的解决方法,欢迎将解决方案带上本链接一起发送给小编。

小编邮箱:dio#foxmail.com (将#修改为@)