跳到主要内容

真假外键

通过关联映射的论述中,我们知道关联映射需要大量的外键。

Jimmer中外键有两种

  • 真外键:

    数据库中存在对应的外键约束

  • 伪外键:

    在开发人员意识中是外键,但是数据库中并没有对应的外键约束

信息

在保存数据时

  • 真外键靠关系型数据库本身的能力保证引用完整性

  • 伪外键靠ORM在上层代码中植入额外检查来保证引用完整性

这种差异对用户透明,用户只需要配置外键的真伪即可,无需修改业务代码。

明确指定真外键

  • 基于外键的关联属性

    Book.java
    @Entity
    public interface Book {

    @ManyToOne
    @JoinColumn(foreignKeyType = ForeignKeyType.REAL)
    BookStore store();

    ...省略其他代码...
    }
  • 基于中间表的关联属性

    Book.java
    @Entity
    public interface Book {

    @ManyToMany
    @JoinTable(
    joinColumns = @JoinColumn(foreignKeyType = ForeignKeyType.REAL),
    inverseJoinColumns = @JoinColumn(foreignKeyType = ForeignKeyType.REAL)
    )
    List<Author> authors();

    ...省略其他代码...
    }
    信息

    和之前的例子不同,这里

    • 配置JoinTable.joinColumns而非JoinTable.joinColumnName

      如果外键只有一列且不想明确指定外键的真伪,joinColumnName是一种简化配置;否则,应使用joinColumns

    • 配置JoinTable.inverseJoinColumns而非JoinTable.inverseJoinColumnName

      如果外键只有一列且不想明确指定外键的真伪,inverseJoinColumnName是一种简化配置;否则,应使用inverseJoinColumns

警告

如果数据库方言不支持外键, (比如:org.babyfish.jimmer.sql.dialect.TiDBDialect,则不能明确指定真外键。

因为,作为一个分布式关系型数据库,TiDB不支持外键约束。

明确指定伪外键

  • 基于外键的关联属性

    Book.java
    @Entity
    public interface Book {

    @ManyToOne
    @Nullable
    @JoinColumn(foreignKeyType = ForeignKeyType.FAKE)
    BookStore store();

    ...省略其他代码...
    }
  • 基于中间表的关联属性

    Book.java
    @Entity
    public interface Book {

    @ManyToMany
    @JoinTable(
    joinColumns = {@JoinColumn(foreignKeyType = ForeignKeyType.FAKE)},
    inverseJoinColumns = {@JoinColumn(foreignKeyType = ForeignKeyType.FAKE)}
    )
    List<Author> authors();

    ...省略其他代码...
    }

不明确指定外键的真伪

如果不想明确指定外键的真伪,可使用@JoinColumn(foreignKeyType = ForeignKeyType.AUTO)

由于ForeignKeyType.AUTO@JoinColumn注解的默认配置,所以,更好的选择是对此不做任何配置。

因此,代码和关联映射中的示范的代码无差异,这里无需再做示范代码。

如果没有明确指定外键的真伪,则通过以下两个步骤自动决定外键的真伪

  1. 如果数据库方言不支持外键, (比如:org.babyfish.jimmer.sql.dialect.TiDBDialect,则判定为伪外键。

    此时,已经有了判定结果,提前返回,不会执行步骤2

  2. 如果第一步无法完成判定,则参见Jimmer的全局配置is-foreign-key-enabled-by-default

    如果此配置为true,则判定为真外键;否则,判定为伪外键。

    该配置默认为true,用户可以将其覆盖为false

    • 如果使用SpringBoot

      修改application.ymlapplication.properties,将jimmer.is-foreign-key-enabled-by-default设置为false

    • 如果不使用SpringBoot

      JSqlClient sqlClient = JSqlClient
      .newBuilder()
      .setForeignKeyEnabledByDefault(false)
      ...省略其他配置...
      .build();