首页 > 解决方案 > 从 Hibernate 3.6 迁移到 4.2:Hibernate 自动生成外键

问题描述

正如标题所示:我目前正在从 Hibernate 3.6 迁移到 4.2。

问题

升级后,Hibernate 开始自动生成指向同一张表的外键。现在,当尝试保持新客户时,ConstraintViolationException会抛出 a。

细节

这是我的意思的图片:

在此处输入图像描述

下面是对应类的代码:

@Entity
@Table(name = "customers")
@Inheritance(strategy = InheritanceType.JOINED)
public abstract class Customer extends AbstractModel {

    public Customer(final Provider provider) {
        this.provider = provider;
    }

    @Required
    @ManyToOne(cascade = CascadeType.REFRESH)
    public Provider provider;

    @MaxSize(1023)
    public String note;
    public String getNote() { return note; }

    ...

}

如您所见,它扩展自AbstractModelwhich is a@MappedSuperclass并包含id用作我们所有模型类的主键的属性。这是一个@GeneratedValue

它本身就是一个超类。我不知道它是否重要,所以我只想包含其子类之一的代码和架构:

在此处输入图像描述

以及对应的代码:

@Entity
@Table(name="unregistered_customers")
public class UnregisteredCustomer extends Customer {

    @MaxSize(MAX_SIZE_OF_NAMES_AND_IDENTIFIERS)
    @Column(nullable = false, length = MAX_SIZE_OF_NAMES_AND_IDENTIFIERS)
    public String userName;

    @Email
    @MaxSize(MAX_SIZE_OF_EMAIL_ADDRESSES)
    @Column(unique = false, length = MAX_SIZE_OF_EMAIL_ADDRESSES)
    public String email;

    @MaxSize(MAX_SIZE_OF_NAMES_AND_IDENTIFIERS)
    @Column(length = MAX_SIZE_OF_NAMES_AND_IDENTIFIERS)
    public String mobile;

    public UnregisteredCustomer(final Provider provider) {
        super(provider);
    }

研究

我已经查看了迁移指南,但其中似乎没有任何内容与我的问题有关。我还查看了 Hibernate 文档,尤其是处理@Inheritance. 可悲的是,我没有发现任何有关自动生成的外键的信息。

问题

如何阻止 Hibernate 添加这个自引用外键?

编辑 1 根据要求,超类:

@MappedSuperclass
public abstract class AbstractModel extends AbstractBaseModel {

    @Id
    @GeneratedValue
    public Long id;

    public Long getId() {
        return id;
    }

    @Override
    public Object _key() {
        return id;
    }

}

还有,超类的超类:

@MappedSuperclass
public abstract class AbstractBaseModel extends GenericModel {

    public static final int MAX_SIZE_OF_NAMES_AND_IDENTIFIERS = 80;
    public static final int MAX_SIZE_OF_COMMENTS_AND_DESCRIPTIONS = 5000;
    public static final int MAX_LIST_SIZE = 30;
    public static final int MAX_SIZE_OF_EMAIL_ADDRESSES = 255;
    public static final int MAX_SIZE_OF_JSON_CONTENT_FIELDS = 65535;

    @Column(nullable = false, unique = true)
    public String uuid;

    @Column(nullable = false)
    public Long created;
    public DateTime getCreatedAsDate() {
        return DateUtil.dateTimeWithSystemTimezone(created);
    }

    @Column(nullable = false)
    public Long lastModified;


    @PrePersist
    protected void prePersist() {
        final Long nowInMillis = DateUtil.dateTimeWithSystemTimezone().getMillis();

        if (uuid == null) {
            uuid = UuidUtil.newUUIDAsString();
            Logger.trace("Created new Uuid for entity: %s", uuid);
        }
        if (created == null) {
            created =  nowInMillis;
        }
        if (lastModified == null) {
            lastModified = nowInMillis;
        }
    }

    @PreUpdate
    protected void preUpdate() {
        lastModified = DateUtil.dateTimeWithSystemTimezone().getMillis();
    }
   
    
    @Override
    public boolean equals(final Object obj) {
        if (this == obj) {
            return true;
        }
        if (obj == null) {
            return false;
        }
        final AbstractBaseModel other = (AbstractBaseModel) obj;
        return new EqualsBuilder().append(uuid, other.uuid).isEquals();
    }

    @Override
    public int hashCode() {
        return new HashCodeBuilder().append(uuid).toHashCode();
    }

}

标签: javamysqlhibernate

解决方案


将 @Inheritance(strategy = InheritanceType.JOINED) 放到父实体(AbstractModel)而不是子实体。并在您的子实体中使用 @PrimaryKeyJoinColumn 自定义外键约束。请查看https://www.baeldung.com/hibernate-inheritance上的第 4 部分(连接表)以更清楚地看到它!


推荐阅读