保存链接表时出错:无法将值NULL插入列'ParentId',表'TableParentChild';列不允许为空。插入失败

问题描述 投票:0回答:1

我正在编写一个导入,需要将两种类型的数据(父级和子级)保存到各自的表和一个链接表(parentChild)中以将它们连接起来。我知道这个错误是不言自明的,并且有很多其他人提出类似的问题 - 但这是不同的。在这里,chatGpt,在项目中搜索示例和我自己的东西,我一直无法想出可行的东西。我认为这是 FK 约束的问题,但这与我在其他地方使用的模式相同。它显然*认为*我正在发送null,但不知怎的,它并没有从正在链接的两个对象中提取id。

我无法发布实际的代码,但这里有一个重现这种情况的 noddy 版本。


DDL(在mssql中运行):

CREATE SEQUENCE Project.TableParentIdSeq START WITH 1 INCREMENT BY 1;
CREATE SEQUENCE Project.TableChildIdSeq START WITH 1 INCREMENT BY 1;
CREATE SEQUENCE Project.TableParentChildIdSeq START WITH 1 INCREMENT BY 1;

CREATE TABLE Project.TableParent
(
    ParentId BIGINT NOT NULL CONSTRAINT DF_Project_TableParent_TableParentIdSeq DEFAULT (NEXT VALUE FOR Project.TableParentIdSeq),
    ParentName VARCHAR(10)  NOT NULL
);

CREATE TABLE Project.TableChild
(
    ChildId BIGINT NOT NULL CONSTRAINT DF_Project_TableChild_TableChildIdSeq DEFAULT (NEXT VALUE FOR Project.TableChildIdSeq),
    ChildName VARCHAR(10)  NOT NULL
);

CREATE TABLE Project.TableParentChild
(
    ParentChildId BIGINT NOT NULL CONSTRAINT DF_Project_TableParentChild_TableParentChildIdSeq DEFAULT (NEXT VALUE FOR Project.TableParentChildIdSeq),
    ParentId BIGINT NOT NULL,
    ChildId BIGINT NOT NULL
);

ALTER TABLE Project.TableParent
    ADD
        CONSTRAINT PK_TableParent PRIMARY KEY (ParentId);

ALTER TABLE Project.TableChild
    ADD
        CONSTRAINT PK_TableChild PRIMARY KEY (ChildId);

ALTER TABLE Project.TableParentChild
    ADD
        CONSTRAINT PK_TableParentChild PRIMARY KEY (ParentChildId),
        CONSTRAINT FK_TableParentChild_ParentId FOREIGN KEY (ParentId) REFERENCES Project.TableParent (ParentId),
        CONSTRAINT FK_TableParentChild_ChildId FOREIGN KEY (ChildId) REFERENCES Project.TableChild (ChildId);

实体(每个实体都带有@entity/getter/setter/所有参数/无参数/表):

public class ParentEntity  implements Serializable {
    @Id
    @Column(name = "ParentId")
    @GeneratedValue(generator = "TableParentIdSeq")
    @SequenceGenerator(name = "TableParentIdSeq", sequenceName = "Project.TableParentIdSeq", allocationSize = 1)
    private Long id;

    private String parentName;

    @OneToMany(cascade = {CascadeType.ALL}, mappedBy = "parent", orphanRemoval = true)
    private List<ParentChildEntity> children = new ArrayList<>();

    public ParentEntity(String parentName) {
        this.parentName = parentName;
    }
}
public class ChildEntity implements Serializable {
    @Id
    @Column(name = "ChildId")
    @GeneratedValue(generator = "TableChildIdSeq")
    @SequenceGenerator(name = "TableChildIdSeq", sequenceName = "Project.TableChildIdSeq", allocationSize = 1)
    private Long id;

    private String childName;

    public ChildEntity(String childName) {
        this.childName = childName;
    }
}
public class ParentChildEntity  implements Serializable {
    @Id
    @Column(name = "ParentChildId")
    @GeneratedValue(generator = "TableParentChildIdSeq")
    @SequenceGenerator(name = "TableParentChildIdSeq", sequenceName = "Project.TableParentChildIdSeq", allocationSize = 1)
    private Long id;

    @ManyToOne //(cascade = {CascadeType.ALL})
    @JoinColumn(name = "ParentId", referencedColumnName = "ParentId", insertable = false, updatable = false)
    private ParentEntity parent;

    @ManyToOne
    @JoinColumn(name = "ChildId", referencedColumnName = "ChildId", insertable = false, updatable = false)
    private ChildEntity child;

    public ParentChildEntity (ParentEntity parent, ChildEntity child) {
        this.parent =  parent;
        this.child = child;
    }
}

每个表都有自己的存储库,扩展 JpaRepository 并仅使用 save()。


服务层代码:

    @Transactional
    public void populateTables() {
        ParentEntity parentSaved = parentRepository.saveAndFlush(new ParentEntity("Parent 1"));
        ChildEntity childSaved = childRepository.saveAndFlush(new ChildEntity("Child A"));
        parentChildRepository.save(new ParentChildEntity(parentSaved, childSaved));
    }

如果我不将最终保存到链接表,则父级和子级将成功保存。 在调试中,我可以看到父级和子级都有 id,并且在一切就位的情况下调用了parentChild save()。 我原以为子类应该像父类一样有一个 OneToMany 列表,因为它与父类的链接表有类似的关系,但 chatGpt 另有说法。 使列可为空(不是我想要做的)只是意味着它们在与数据一起保存时设置为空。 id 生成适用于所有三个表。

运行时会在控制台中出现此错误: 无法将 NULL 值插入表“Project.TableParentChild”的“ParentId”列;列不允许为空。 INSERT 失败。

将调试中的最终 save() 评估为 saveAndFlush() 给出: 无法执行语句; SQL [不适用];约束[空]

有什么想法吗?希望我不会太愚蠢。

java sql-server spring-boot hibernate jpa
1个回答
0
投票

问题已解决。

这取决于 ParentChildEntity 中父级和子级的“insertable = false,updatable = false”。我记得我认为他们在之前的工作中看起来有点违反直觉,但这就是模式并且它有效。这里没有。

© www.soinside.com 2019 - 2024. All rights reserved.