【问题标题】:JPA + Hibernate + Spring - Parent Child persistence with generating ID leads to foreign key errorJPA + Hibernate + Spring - 生成ID的父子持久性导致外键错误
【发布时间】:2016-06-21 16:21:29
【问题描述】:

我在 IntelliData 回答后编辑了我的问题。

数据库

在我拥有的数据库中,我无法进行任何更改:

Table A {
   ID NUMBER(10, 0) NOT NULL 
   DATE_DEBUT DATE NOT NULL 
   DATE_FIN DATE
   .....
}

Table B {
   ID NUMBER(10, 0) NOT NULL 
   B_ID VARCHAR2(10 BYTE) NOT NULL
}

表A中的ID是PK,是生成的值。
在表 B (ID, B_ID) 中是 PK。
B.ID 在 A.ID 上是 FK。

实体

一个

@Entity
@Table(name = "A")
public class A implements Serializable {
    @Id
    @GeneratedValue(strategy = GenerationType.SEQUENCE, generator = "aIdGenerator")
    @SequenceGenerator(name = "aIdGenerator", sequenceName = "A_SEQ", allocationSize = 1)
    @Column(name = "ID")
    private Integer id;

    @Column(name = "DATE_DEBUT")
    private LocalDate dateDebut;

    @Column(name = "DATE_FIN")
    private LocalDate dateFin;

    @OneToMany(mappedBy = "a", fetch = FetchType.LAZY, cascade = { CascadeType.PERSIST })
    private List<B> bs;
    .
    .
    .
}

B

@Entity
@Table(name = "B")
public class B implements Serializable {

    @Id
    @ManyToOne
    @JoinColumn(name = "ID", referencedColumnName = "ID")
    private A a;

    @Id
    @Column(name = "B_ID")
    private String bID;

    public B(final A a, final String bID) {
        super();
        this.a = a
        this.bID= bID;
    }
    .
    .
    .
}

存储库

public interface aRepository extends JpaRepository<A, Integer> {
    // nothing more
}

我的 java

A a= new A();
a.setDateDebut(LocalDate.now());
a.setDateFin(LocalDate.now());

B bs = new ArrayList<B>();
bs.add(new B(a, "aaa"));
bs.add(new B(a, "bbb"));
bs.add(new B(a, "ccc"));

a.setBs(bs);

myrepo.saveAndFlush(a);

问题(最终)

ORA-01400: cannot insert NULL into ("B"."ID") ---> RESOLVED by IntelliData

但现在我明白了

ORA-02291: integrity constraint (FK_B_ID) violated - parent key not found

我不明白为什么,因为 Hibernate 以良好的顺序插入并且具有良好的价值......我设法得到了这些日志:

DEBUG [main] org.hibernate.SQL(109) - insert into GOELAND_DEPLOI (DATE_DEBUT, DATE_FIN, ID) values (?, ?, ?)
Hibernate: insert into A (DATE_DEBUT, DATE_FIN, ID) values (?, ?, ?)
TRACE [main] o.h.t.d.sql.BasicBinder(81) - binding parameter [1] as [DATE] - [2016-06-22]
TRACE [main] o.h.t.d.sql.BasicBinder(81) - binding parameter [1] as [DATE] - [2016-06-22]
TRACE [main] o.h.t.d.sql.BasicBinder(81) - binding parameter [2] as [DATE] - [2016-06-22]
TRACE [main] o.h.t.d.sql.BasicBinder(81) - binding parameter [2] as [DATE] - [2016-06-22]
TRACE [main] o.h.t.d.sql.BasicBinder(81) - binding parameter [3] as [INTEGER] - [127]
DEBUG [main] org.hibernate.SQL(109) - insert into B (ID, B_ID) values (?, ?)
Hibernate: insert into B (ID, B_ID) values (?, ?)
TRACE [main] o.h.t.d.sql.BasicBinder(81) - binding parameter [1] as [INTEGER] - [127]
TRACE [main] o.h.t.d.sql.BasicBinder(81) - binding parameter [2] as [VARCHAR] - [TEST]
DEBUG [main] o.h.e.j.spi.SqlExceptionHelper(139) - could not execute statement [n/a]
java.sql.SQLIntegrityConstraintViolationException: ORA-02291: violation de contrainte d'intégrité (COMMON.FK_B_ID) - clé parent introuvable

如果还不够,我可以在 myrepo.saveAndFlush(a) 上放置更多日志;

【问题讨论】:

    标签: java spring hibernate jpa annotations


    【解决方案1】:

    为了使 b.ID 有值,您必须将 a 添加到 b,如:

    b.setA(a);
    

    B 的构造函数设置字段 b.bId,但不设置字段 b.a ...


    更新:

    尝试改变这个:

    @OneToMany(mappedBy = "a", fetch = FetchType.LAZY, cascade = {   CascadeType.PERSIST })
    private List<B> bs;
    

    到这里:

    @OneToMany(fetch=FetchType.LAZY, cascade={CascadeType.PERSIST,CascadeType.MERGE, CascadeType.REMOVE})
    @JoinColumn(name="ID")
    @NotNull
    private List<B> b;
    

    类似于this 帖子上的答案。请让我知道它是否有效。

    【讨论】:

    • 感谢它让我的案子动起来,即使它没有解决所有问题。我已经根据您的更改编辑了我的问题。
    • 最后我做到了:@OneToMany(fetch=FetchType.LAZY, cascade={CascadeType.PERSIST,CascadeType.MERGE, CascadeType.REMOVE}) @JoinColumn(name="ID", nullable = false) private List&lt;B&gt; b; 但是我必须从 B 类中删除 A 如果不是休眠尝试在插入 B 期间设置 3 个值而不是 2 个值。感谢您的帮助
    【解决方案2】:

    似乎另一个人更改了您的 ID。 你确定你的 A 表上没有更新值的触发器

    例如:

    Hibernate : seq.nextVal => 52
    Hibernate : insert into A values (52...)
    Database  : trigger on insert A : call to seq.nextVal => 53
    Databse   : Value really inserted into A : 53
    

    Hibernate 不知道该值已更改。

    两种解决方案:

    • 编辑您的触发器:如果设置了 id,则不要获取新的触发器
    • 分两步:插入 A,获取 A,插入 B(不推荐)

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2011-09-22
      • 2017-08-18
      • 2011-04-21
      • 1970-01-01
      相关资源
      最近更新 更多