Issue #606: Issue with cascade delete & add/remove

Type: Bug ReoprtPriority: NormalStatus: ClosedReplies: 2
#1

Hi,

Please see the attached sample project (important: classes need to be enhanced as done in the pom.xml file).

What happens: We have two entities Address & Contact. Contact keeps a collection of Address which cascades deletes (orphanRemoval=true) to its children which is what we want. However, when removing an Address from the collection and immediately adding it again to the collection (within one transaction!) then the Address entity is yet removed from the database, eventhough it has never been deleted from the collection (at least, until the transaction is comitted).

This is a show stopper for us right now though so appreciate help / fix soon,

BTW -> what happens to all Address Entities within the collection of a Contact when we delete the Contact? Is that cascaded or do we need to clear the collection first, commit that and then remove the Contact?

thanks!

#2
Any Update on this? Still can't figure a workaround or anything though can't continue to work on with this issue.. Thanks!
#3

Here is a simplified version of the test. For getting higher priority - please submit tests in this format:

import java.util.*;
import javax.persistence.*;

public class T606 {

    public static void main(String[] args) {
           
        EntityManagerFactory emf =
            Persistence.createEntityManagerFactory(
                "objectdb://localhost:6136/test/test.tmp;drop;admin");
      
        EntityManager em = emf.createEntityManager();
        Contact contact = new Contact("TEST");
        contact.getAddresses().add(new Address("1", "1", "1"));
        contact.getAddresses().add(new Address("2", "2", "2"));
        em.getTransaction().begin();
        em.persist(contact);
        em.getTransaction().commit();
        printCounts(em);
        em.close();

        em = emf.createEntityManager();
        contact = (Contact) em.createQuery("SELECT FROM Contact")
            .setMaxResults(1).getSingleResult();
        em.getTransaction().begin();
        Address address_1 = contact.getAddresses().get(0);
       
        // Remove and add address again -> will be gone
        contact.getAddresses().remove(address_1);
        contact.getAddresses().add(address_1);

        em.getTransaction().commit();
        printCounts(em);
        em.close();

        emf.close();
    }

    private static void printCounts(EntityManager em) {
        int Address_1_Count = ((Long) em.createQuery(
            "SELECT COUNT(a) FROM Address a WHERE street = '1'")
            .getSingleResult()).intValue();
        int Address_2_Count = ((Long) em.createQuery(
            "SELECT COUNT(a) FROM Address a WHERE street = '2'")
            .getSingleResult()).intValue();
        System.out.println("Address_1 Count: " +
            Integer.toString(Address_1_Count));
        System.out.println("Address_2 Count: " +
            Integer.toString(Address_2_Count));
    }

    @Entity
    public static class Contact {
        private String name = null;
        @OneToMany(cascade = CascadeType.ALL, orphanRemoval = true)
        private List<Address> addresses = null;

        public Contact(String name) {
            this.name = name;
        }

        public Contact() {
        }
       
        public List<Address> getAddresses() {
            if (addresses == null)
                addresses = new ArrayList<Address>();
            return addresses;
        }
    }

    @Entity
    public static class Address {
        private String street = null;
        private String no = null;
        private String city = null;

        public Address(String street, String no, String city) {
            this.street = street;
            this.no = no;
            this.city = city;
        }

        public Address() {
        }
    }
}

As you indicated, the behavior when using enhancement and using reflection is different. This is the result of different implementation of the action in these two modes.

However, this is not a bug, since according to JPA: "Portable applications must otherwise not depend upon a specific order of removal, and must not reassign an entity that has been orphaned to another relationship or otherwise attempt to persist it", so in your application you should avoid adding the address again after removal.

ObjectDB Support

Reply