外键的 Flyway 和 PostgreSQL 可空定义仍然生成非空约束

Flyway and PostgreSQL nullable definition of foreign key still generates a non-null constraint

我将 Spring Boot 和 Flyway 与此初始化脚本一起使用:

CREATE TABLE ADDRESS(
    ID bigserial NOT NULL PRIMARY KEY
                    );

CREATE TABLE ROLE(
    ID bigserial NOT NULL PRIMARY KEY
);

CREATE TABLE PERSON(
    ID bigserial NOT NULL PRIMARY KEY,
    FIRST_NAME VARCHAR(255),
    LAST_NAME VARCHAR(255),
    ADDRESS bigserial NOT NULL REFERENCES ADDRESS (ID),
    ROLE bigserial REFERENCES ROLE (ID)                  -- notice here is no 'not null'
);

所有table之间的关系是:

一旦我启动应用程序(我也尝试 post 查询直接到 PostgreSQL 数据库模式),就会以某种方式生成约束 not-null PERSONROLE tables.

使用 DataGrip,我 select SQL 脚本 -> 生成 DDL 以查询控制台 并获取tables 的 DDL(见下文,为简洁起见省略了新行和角色定义)。

令我惊讶的是,NOT NULL 在那里,尽管我没有定义这样的约束。除了改变 table 之外如何摆脱它?

create table if not exists address
(
    id bigserial not null
        constraint address_pkey primary key
);

create table if not exists role
(
    id bigserial not nullconstraint role_pkey primary key
);

create table if not exists person
(
    id bigserial not null 
        constraint person_pkey primary key,
    first_name varchar(255),
    last_name varchar(255),
    address bigserial not null 
        constraint person_address_fkey references address,
    role bigserial not null                                   -- why is 'not null' here?
        constraint person_role_fkey references role
);

我使用的(通过SELECT version())的PostgreSQL版本是:

PostgreSQL 10.13, compiled by Visual C++ build 1800, 64-bit

"8.1.4. Serial Types":

The data types smallserial, serial and bigserial are not true types, but merely a notational convenience for creating unique identifier columns (similar to the AUTO_INCREMENT property supported by some other databases). In the current implementation, specifying:

CREATE TABLE tablename (
    colname SERIAL
);

is equivalent to specifying:

CREATE SEQUENCE tablename_colname_seq AS integer;
CREATE TABLE tablename (
    colname integer NOT NULL DEFAULT nextval('tablename_colname_seq')
);
ALTER SEQUENCE tablename_colname_seq OWNED BY tablename.colname;

注意 NOT NULL

不要使用 bigserial 作为 外键 键。那没有多大意义。只需使用 bigint.

CREATE TABLE IF NOT EXISTS person
                           (...
                            role bigint REFERENCES role);

可能的解决方案一: 将 Biserial 更改为 Bigint 不会删除在 运行 springboot 中的 flyway 写入 postgres DB 时设置为外键列的空约束(至少对于我的情况)

  • postgres:11.3-alphine 3.4
  • 飞行路线:8.0.5

为了安全起见,需要添加脚本来将列更改为可为空

ALTER TABLE mytable ALTER COLUMN mycolumn DROP NOT NULL;

Change Postgres column to nullable

可能的解决方案2: 当 Spring 引导将 JPA Hibernate ddl 配置设置为 createcreate-dropupdate 时,flyway DB 迁移脚本将由 JPA 实体属性更新。 JPA 实体可以添加 NOT NULL 约束。

将 JPA Hibernate ddl 配置更改为 nonevalidate 将确保仅使用 flyway 脚本来创建模式。