Java JPA插入父项/子项会导致MySQLIntegrityConstraintViolationException

Java JPA插入父项/子项会导致MySQLIntegrityConstraintViolationException,java,mysql,hibernate,jpa,Java,Mysql,Hibernate,Jpa,这已经被问了很多次了,但是我没有找到任何好的答案,所以我会再问一遍 我的父母子女单向关系如下: @Entity @Table(name = "PARENT") public class Parent { @Id @GeneratedValue(strategy = GenerationType.IDENTITY) @Column(name = "ID") private Long parentId; @OneToMany(fetch = FetchTyp

这已经被问了很多次了,但是我没有找到任何好的答案,所以我会再问一遍

我的父母子女单向关系如下:

@Entity
@Table(name = "PARENT")
public class Parent {
    @Id
    @GeneratedValue(strategy = GenerationType.IDENTITY)
    @Column(name = "ID")
    private Long parentId;

    @OneToMany(fetch = FetchType.EAGER, cascade = CascadeType.PERSIST)
    @JoinTable(name = "CHILD", joinColumns = @JoinColumn(name = "parent_id"), inverseJoinColumns = @JoinColumn(name = "ID"))
    private List<Child> children;
}

@Entity
@Table(name = "CHILD")
public class Child {
    @Id
    @GeneratedValue(strategy = GenerationType.IDENTITY)
    @Column(name = "ID")
    private Long id;

    @Column(name = "PARENT_ID")
    private Long parentId;

    //some other field
}
@实体
@表(name=“PARENT”)
公共类父类{
@身份证
@GeneratedValue(策略=GenerationType.IDENTITY)
@列(name=“ID”)
私人长父ID;
@OneToMany(fetch=FetchType.EAGER,cascade=CascadeType.PERSIST)
@JoinTable(name=“CHILD”、joinColumns=@JoinColumn(name=“parent\u id”)、inverseJoinColumns=@JoinColumn(name=“id”))
私人名单儿童;
}
@实体
@表(name=“CHILD”)
公营儿童{
@身份证
@GeneratedValue(策略=GenerationType.IDENTITY)
@列(name=“ID”)
私人长id;
@列(name=“PARENT\u ID”)
私人长父ID;
//其他领域
}
我创建父对象的实例,为其分配子对象列表,并尝试将其持久化:

Parent p = new Parent();
List<Child> children = new ArrayList<Child>();
Child c = new Child();
children.add(c);
p.addChildren(children);
em.merge(p);
Parent p=newparent();
List children=new ArrayList();
Child c=新的Child();
添加(c);
p、 儿童(儿童);
em.merge(p);
当代码运行时,我得到以下异常:

MySQLIntegrityConstraintViolationException:无法添加或更新 子行:外键约束失败 (
testdb
child
,CONSTRAINT
parent\u fk
外键(
parent\u id
)引用 更新时不删除任何操作(无操作)

我假设这是因为在尝试插入子对象时父对象未完全插入

如果我不将子对象添加到父对象中,父对象就可以很好地插入。 我尝试了转换生成价值生成策略,但没有效果

你知道如何同时插入父母和孩子吗

编辑:即使我先持久化父对象,仍然会得到相同的错误。我确定这是因为未在子对象中设置父对象id;子项是默认构造的,因此父项_id设置为0,该值不存在,因此进行外键约束验证


有没有办法让jpa自动设置分配给父实例的子对象的父对象id?

我知道使用
em.persistens(…)
将新的父对象与子对象持久化对我很有效

使用
em.merge(…)
,我真的不知道,但听起来它应该可以工作,但很明显,您遇到了麻烦,因为您的JPA实现试图将子对象持久化到父对象之前

也许可以检查一下这是否适合您:

我不知道这是否与你的问题有关,但请记住
em.merge(p)将返回一个托管实体。。。而
p
将保持未管理状态,您的孩子将链接到
p

A) 尝试
em.persistens(…)
而不是
em.merge(…)

如果你不能

B) 您正在合并父级
。。。您将
cascade
设置为
CascadeType.PERSIST
。试着把它改成

  • cascade=CascadeType.ALL

  • cascade={CascadeType.PERSIST,CascadeType.MERGE}

我知道,
合并
将持久化新创建的实体,并应表现为
持久化
,但这些是我最好的提示。

您想要实现的目标可以通过此代码实现

    @Entity
    @Table(name = "PARENT")
    public class Parent {
        @Id
        @GeneratedValue(strategy = GenerationType.IDENTITY)
        @Column(name = "ID")
        private Long parentId;

        @OneToMany(cascade = CascadeType.PERSIST)
        private List<Child> children;
    }

    @Entity
    @Table(name = "CHILD")
    public class Child {
        @Id
        @GeneratedValue(strategy = GenerationType.IDENTITY)
        @Column(name = "ID")
        private Long id;

        @ManyToOne
        Parent parent;
    }
@实体
@表(name=“PARENT”)
公共类父类{
@身份证
@GeneratedValue(策略=GenerationType.IDENTITY)
@列(name=“ID”)
私人长父ID;
@OneToMany(cascade=CascadeType.PERSIST)
私人名单儿童;
}
@实体
@表(name=“CHILD”)
公营儿童{
@身份证
@GeneratedValue(策略=GenerationType.IDENTITY)
@列(name=“ID”)
私人长id;
@许多酮
父母;
}

您的关系不必是双向的。这里的评论中有一些错误信息

您还说您已经将字段“parentId”添加到子实体中,因为您假设JPA需要“了解”父字段,以便可以设置值。根据您提供的注释,问题不在于JPA不知道该字段。问题是您提供了有关该字段的“太多”信息,但这些信息在内部并不一致

将父项中的字段和注释更改为:

@OneToMany(fetch = FetchType.EAGER, cascade = CascadeType.PERSIST)
@JoinColumn(name = "parent_id")
private List<Child> children;
这完美地反映了你想要什么。将创建父项。创建子条目,然后更新子记录以正确设置外键

如果改为添加注释

@OneToMany(fetch = FetchType.EAGER, cascade = CascadeType.PERSIST)
@JoinColumn(name = "parent_id", nullable = false)
private List<Child> children;

因此,从一开始就正确地设置FK。

将updateable=false添加到父实体解决了在子表上执行insert和updated的问题。然而,我不知道为什么会这样,事实上,我不认为我所做的是正确的,因为这意味着如果必须的话,我以后无法更新子表。

如果这应该是单向关系,那么为什么要将
parentId
放在
child
实体中?外键存储在联接表中。@ventsyv-对其进行了正确的总结,子端根本不需要该id。@Biraj Choudhury我在POJO中不需要它,但在表中需要它,所以我假设JPA需要“知道”它,以便它可以将其设置为正确的值。如果我将其从POJO中删除,则为插入子项而生成的查询没有设置parent_id字段,因此无法工作。您说您需要一个单向关系,这意味着您有三个表parent(parent id-PK、ChildId-FK、其他字段)、child(child id-PK)、parent_-child(子Id-一对多关系的父Id)。您将
@OneToMany(fetch = FetchType.EAGER, cascade = CascadeType.PERSIST)
@JoinColumn(name = "parent_id", nullable = false)
private List<Child> children;
insert into CHILD (ID, parent_id) values (default, ?)