如何创建可选的外键引用?

时间:2015-12-14 11:48:07

标签: java hibernate postgresql

我想创建一个在此示例中按someId映射对象的外键:

@Entity
public class MyEntity {

    private int someId;

    @ManyToOne
    @JoinColumn(name = "someId", foreignKey = @ForeignKey(name="fk_id"), insertable = false, updatable = false, nullable = true)
    private MyObject obj;
}

如您所见:someId也会使用相同的ID创建对MyObject的外键引用。

问题:我希望能够设置someId,同时表MyObject中的my_object_table可能

这可能吗?

我设置了someId但是外表中不存在相同的id,我在持久性上遇到以下错误:

Caused by: org.postgresql.util.PSQLException: ERROR: Insert or Update in table "my_entity" violates forgein key constraint "fk_id".
  Detail: Key (some_id)=(940) is not contained within table "my_object_table".
    at org.postgresql.core.v3.QueryExecutorImpl.receiveErrorResponse(QueryExecutorImpl.java:2270)
    at org.postgresql.core.v3.QueryExecutorImpl.processResults(QueryExecutorImpl.java:1998)
    at org.postgresql.core.v3.QueryExecutorImpl.execute(QueryExecutorImpl.java:255)

1 个答案:

答案 0 :(得分:2)

拥有有时强制执行但有时不执行的外键是没有意义的。

通常是"可选"外键是具有外键引用的表可以为空的外键。如果它不为null,则通过检查引用的表中是否存在引用值来强制执行外键约束。这样的约束允许MyEntity存在,其中obj列引用了不存在的MyObject。它只允许 null obj列。

您似乎想要一个外键约束,它不会检查或不关心引用的值是否存在。即允许MyEntity.obj具有与任何有效MyObject不对应的值。这根本不符合逻辑。它被称为"没有外键"。这就像要求一个独特的约束,它并不总是唯一的。

现在,您可能希望定义仅对某些行子集强制执行的外键约束,例如: "仅当soft_deleted列为false"时才检查外键约束。 PostgreSQL目前不支持外键;它类似于部分唯一索引,但对于外键。

也许您希望能够在交易过程中暂时违反外键,只要它在交易结束时再次有效。根据手册,这可以使用DEFERRABLE外键约束。我不知道Hibernate是否支持创建它们或管理它们,但是如果你使用SQL在数据库模式中使用DEFERRABLE INITIALLY DEFERED定义它们,它应该"只是工作"使用Hibernate,在提交时检查FK而不是立即。