Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Duplicate a collection of entities and persist in Hibernate/JPA

I want to duplicate a collection of entities in my database. I retreive the collection with:

CategoryHistory chNew = new CategoryHistory();
CategoryHistory chLast =  (CategoryHistory)em.createQuery("SELECT ch from CategoryHistory ch WHERE ch.date = MAX(date)").getSingleResult;
List<Category> categories = chLast.getCategories();
chNew.addCategories(categories)// Should be a copy of the categories: OneToMany

Now i want to duplicate a list of 'categories' and persist it with EntityManager. I'm using JPA/Hibernate. UPDATE

After knowing how to detach my entities, i need to know what to detach: current code:

    CategoryHistory chLast =  (CategoryHistory)em.createQuery("SELECT ch from CategoryHistory ch WHERE ch.date=(SELECT MAX(date) from CategoryHistory)").getSingleResult();
    Set<Category> categories =chLast.getCategories();

    //detach
    org.hibernate.Session session = ((org.hibernate.ejb.EntityManagerImpl) em.getDelegate()).getSession();
    session.evict(chLast);//detaches also its child-entities?       

    //set the realations
    chNew.setCategories(categories);
    for (Category category : categories) {
        category.setCategoryHistory(chNew);
    }
    //set now create date
    chNew.setDate(Calendar.getInstance().getTime());

    //persist
    em.persist(chNew);

This throws a failed to lazily initialize a collection of role: entities.CategoryHistory.categories, no session or session was closed exception.

I think he wants to lazy load the categories again, as i have them detached. What should i do now?

like image 473
Michael Bavin Avatar asked Dec 10 '22 18:12

Michael Bavin


1 Answers

You need to detach your instances from the session. There are three ways to do this:

  1. Close the session (probably not possible in your case).
  2. Serialize the object and deserialize it again.
  3. Clone the object and clear/null the primary key/id field.

Then you must change the business key (so the new instances will return false when calling equals() with an unmodified instance). This is the important step: Without it, Hibernate will reattach the instances to the existing ones in the DB or you'll get other, strange errors.

After that, you can save the new copies just like any other instance.

like image 86
Aaron Digulla Avatar answered May 01 '23 11:05

Aaron Digulla