EliK
EliK

Reputation: 221

JPA Hibernate. Persist parent and children entities with foreign key reference to a parent in one call

I have the following problem: Having a class A

 Class A {
      ...

      @Id
      @GeneratedValue( strategy = GenerationType.IDENTITY )
      @JsonIgnore
      private Long id;

      @OneToMany(cascade=CascadeType.PERSIST, orphanRemoval = true, fetch = FetchType.EAGER)
      @JsonView(View.Extended.class )
      @JoinColumn(name="b_fkey", referencedColumnName = "id")
      List<B> b;
      ...
 }

and class B:

 Class B {
      ...
      private Long b_fkey;
      ...
 }

I am trying to persist it as follows:

 ...
 A a = new A();
 a.setStuff();
 A aa = aDao.save(a);
 // no list of B's

 for(B b : List<B>) {
     b.setB_fkey(aa.getId());
     bDao.persist(b);
 }
 ...

This works perfectly, but I want it to be saved in the following X-way:

 ...
 A a = new A();
 a.setStuff();
 a.setB(List<B>)
 aDao.persist(a);
 ...

now it throws an error "Column 'f_key' cannot be null", because f_key is a foreign key which is referencing not yet generated value of a.id.

Question: how to save it in the "X way"?

Upvotes: 2

Views: 2857

Answers (2)

Keshav
Keshav

Reputation: 1

Could you try the code below:

    Class A {
      ...

      @JsonIgnore
      private Long id; @Id
      @GeneratedValue( strategy = GenerationType.IDENTITY )
      public Long getId()
      {
          return id;
      }

      public void setId(Long id)
      {
          this.id = id;
      }

      @JsonView(View.Extended.class )
      List<B> b;

      @OneToMany(cascade=CascadeType.PERSIST, orphanRemoval = true, fetch = FetchType.EAGER)
      @JoinColumn(name="b_fkey")
      public List<B> getB(List<B> bList){
          return b;
      }      

      public void setB(List<B> bList){
          this.b = bList;
      }

The annotations over getters and setters give you better control over the hibernate columns.

Upvotes: 0

Kirinya
Kirinya

Reputation: 245

I think that you have two problems:

First, you are mapping a bidirectional relationship but only "half-hearted", i.e. you are not mapping A into B, only its ID.

Better map like:

Class B {

  @ManyToOne(...)
  private A a;
}

Second, if you are mapping a bidirectional relationship in Hibernate, you MUST set both sides (see https://howtoprogramwithjava.com/hibernate-onetomany-bidirectional-relationship/).

This is mostly done by having a method like:

Class A {
   void setB(List<B> bs) {
     this.bs = bs;
     for (B b: bs) {
         b.setA(this);
     }
   }
}

If you do not need A in B, you can also go for a unidirectional mapping.

Upvotes: 1

Related Questions