Persistense @OneToMany - @ManyToOne

84 views Asked by At

I'm having trouble persists the following entities:

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

   @Id
   @Column(name = "id", nullable = false)
   private Integer id;

   @OneToMany(fetch = FetchType.LAZY, mappedBy="entityOne")
   private List<EntityTwo> entities;

}

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

   @Id
   @Column(name = "id", nullable = false)
   private Integer id;

   @Inject
   @ManyToOne(fetch=FetchType.LAZY)
   @JoinColumn(name="entityOne", referencedColumnName="id")
   private EntityOne entityOne;

}

In EntityOneDAO:

em.merge(entityOne);

And it is only persisted to EntityOne and not the list of EntityTwo ... How do I persist the list ?

Thanks all

3

There are 3 answers

0
Vlad Mihalcea On BEST ANSWER

You need to take care of both:

  • transitive persistence (using Cascade)
  • synchronizing both end of the bi-directional association.

So EntityOne should Cascade Persist and Merge to EntityTwo:

@OneToMany(fetch = FetchType.LAZY, mappedBy="entityOne", cascade = { CascadeType.PERSIST, CascadeType.MERGE})
private List<EntityTwo> entities = new ArrayList<>();

As you can see, you should always initialize your collection classes to avoid unnecessary null checks.

And it's always better to add the following helper child adding utility in your parent classes (e.g. EntityOne)

public void addChild(EntityTwo child) {
    if(child != null) {
        entities.add(child);
        child.setEntityOne(this);
    }
}

Then you can simply call:

EntityOne entityOne = new EntityOne();
entityOne.setProperty("Some Value");

EntityTwo entityTwo_1 = new EntityTwo();
entityTwo_1.setName("Something"); 

EntityTwo entityTwo_2 = new EntityTwo();
entityTwo_2.setName("Something"); 

entityOne.addChild(entityTwo_1);
entityOne.addChild(entityTwo_2);

entityManager.persist(entityOne);

P.S.

Please remove the @Inject annotation from the EntityTwo class. Entities are not Components. And persist is much more efficient than merge, when you want to insert new entities.

0
Maksym On

Try this:

public class EntityOne implements Serializable  {

   @Id
   @Column(name = "id", nullable = false)
   private Integer id;

   @OneToMany(fetch = FetchType.LAZY, mappedBy="entityOne", 
              cascade = { CascadeType.ALL})
   private List<EntityTwo> entities;

}

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

   @Id
   @Column(name = "id", nullable = false)
   private Integer id;

   @Inject
   @ManyToOne(fetch=FetchType.LAZY)
   @JoinColumn(name="entityOne", referencedColumnName="id")
   private EntityOne entityOne;

}

You can read here, about the CascadeType.

edited.

0
Salih Erikci On

You should explicitly set each entityTwo objects' entityOne field.

Such that:

entityTwo_1.setEntityOne(entityOne);
entityTwo_2.setEntityOne(entityOne);

entityOne.entities.add(entityTwo_1);
entityOne.entities.add(entityTwo_2);
em.merge(entityOne);