JPA with JTA: Persist entity and merge cascaded child entities

吃可爱长大的小学妹 提交于 2019-11-29 13:24:14

Hi i had the same problem today, i ask to the openJPA mailing list with this email:

Hi. I have a problem with insert and updating a reference in the same entity.

Im trying to insert a new object (Exam) that has a reference to another object (Person) and at the same time i want to update an attribute (birthDate) of the Person object. The update never happens although i set CascadeType to ALL. The only way this works is doing a persist and after that a merge operation. Is this normal? Do i have to change something??

I dont like the idea of a "manual update" using merge in the Person object because i don't know how many objects (child object of Exam) the user want to update.

Entities:

public class Exam{  
   @ManyToOne(cascade= CascadeType.ALL)
   @JoinColumn(name = "person_id")
   public Person person;
......
}

public class Person{
    private Date birthDate;
   @OneToMany(mappedBy = "person")
    private List<Exam> exams
.......
}

public class SomeClass{
   public void someMethod(){
      exam = new Exam()
      person.setBirthDate(new Date());
      exam.setPerson(person); 
      someEJB.saveExam(exam);
   }
}

public class someEJB(){

   public void saveExam(Exam exam){
        ejbContext.getUserTransaction().begin();
        em.persist(exam);
        //THIS WORKS
        em.merge(exam.getPerson());
        ejbContext.getUserTransaction().commit();       
   }

}

Do i have to use the MERGE method for every child object?

And the answer was this:

It looks like your problem is that the Exam is new, yet the Person is existing and the existing Entity gets ignored when cascading the persist operation. I believe this is working as expected.

As long as your relationships are set to CascadeType.ALL, you could always change your em.persist(exam); to em.merge(exam);. That would take care of persisting the new exam, and it would also cascade the merge call to the person.

Thanks, Rick


I hope this can help you.

@SputNick ,I solved it by the steps described below.I am going to use your code snippet to demonstrate what I did,

You have Client entity -@OneToMany and ProductOrder entity -@ManyToOne .I will use

// Called when pressing "save" on the "edit..." 
public void edit(T entity) {
 getEntityManager().merge(entity);}

for persistence as it can give me flexibility to save as well as update.

To create Client and corresponding Product orders use

client.set..(some property to be saved);

productOrder.set..(some property to be saved);

//Set productOrder for the client

List<ProductOrder> order = new ArrayList<>();

client.setOrders(order); //Note that this expects a list to be passed

//set client for the productOrder

productOrder.setClient(productOrder);

.edit(client) or .edit(productOrder)

Note that either way will be able to update both entity tables with your changes.

Though late,hope it will help someone

Use @Joincolumn annotation in your ProductOrder entity, please see below.

   @Entity
   public class ProductOrder implements Serializable, ChildEntity {
   private static final long serialVersionUID = 1L;

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

   @ManyToOne // owning side
   @JoinColumn(name = "PRODUCTORDER_ID", referencedColumnName = "ID")
   //write your database column names into name and referencedColumnName attributes.
   private Client client;

   // other fields, getters and setters
   }

Ensure you are setting both sides of the relationship, you cannot just add the order to the client, you also need to set the client of the order. Also you need to merge both objects that you have changed. If you just merge the client, then the order's client will not be merged (although your cascade you cause it to be merged).

persist does not work, as persist requires that the object being persisted be correct for the persistence context, i.e. not reference detached objects, it must reference managed objects.

Your issue comes from you detaching of the objects. If you did not detach the objects, you would not have the same issues. Normally in JPA you will create an EntityManager, find/query your objects, edit/persist them, call commit. No merging is required.

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!