3

Jpa cascading removes the inverted relationship

 3 years ago
source link: https://www.codesd.com/item/jpa-cascading-removes-the-inverted-relationship.html
Go to the source link to view the article. You can view the picture content, updated content and better typesetting reading experience. If the link is broken, please click the button below to view the snapshot at that time.
neoserver,ios ssh client

Jpa cascading removes the inverted relationship

advertisements

My question is about cascading deletes with JPA and Eclipselink.

I would like to model a simple relationship between two entities: A and B. B references A through a property ref2a (in DB terms B.ref2a is connected to A.id through a foreign key with "ON DELETE CASCADE"). My goal is when an A object is deleted to cascade the delete to all B objects that reference it.

I searched a lot, but I cannot make it work. Most solutions I have found are for the opposite situation: A contains a collection of references to B. This works like a charm. But if the reference is on the B side, I don't know how to do it.

Here is the Code sample:

@Entity
public class A
{
    @Id
    @GeneratedValue
    private Integer id;

    private String name;
    // ...
}

@Entity
public class B
{
    @Id
    @GeneratedValue
    private Integer id;

    private String name;

    @OneToOne
    @JoinColumn(
            foreignKey=@ForeignKey(
                    foreignKeyDefinition="FOREIGN KEY ref2a REFERENCES A id ON DELETE CASCADE"
                    )
            )
    private A ref2a;
    // ...
}

And the test code:

public class CascadeTest extends TestCase
{
    private EntityManagerFactory emf;
    private EntityManager em;

    @Override
    protected void setUp() throws Exception {
        emf = Persistence.createEntityManagerFactory("myDB");
        em = emf.createEntityManager();
    }

    @Override
    protected void tearDown() throws Exception {
        em.close();
        emf.close();
    }

    public void testApp()
    {
        Integer aid = -1, bid = -1;

        try {
            em.getTransaction().begin();

            A a = new A();
            a.setName("My name is A");

            B b = new B();
            b.setRef2a(a);
            b.setName("My name is B, please delete me when A is gone.");

            em.persist(a);
            em.persist(b);

            em.getTransaction().commit();

            aid = a.getId();
            bid = b.getId();

        } finally {
            if (em.getTransaction().isActive())
                em.getTransaction().rollback();
        }

        try {
            em.getTransaction().begin();

            B b = em.find(B.class, bid);
            assertNotNull(b);
            assertEquals("My name is B, please delete me when A is gone.", b.getName());
            assertEquals("My name is A", b.getRef2a().getName());
            assertEquals(aid, b.getRef2a().getId());

            A a = em.find(A.class, aid);
            assertEquals("My name is A", a.getName());

            em.remove(a);
            em.getTransaction().commit();

            em.getTransaction().begin();

            // a should have been removed.
            // This passes OK.
            a = em.find(A.class, aid);
            assertNull(a);

            // Cascading deletes should have deleted also b.
            b = em.find(B.class, bid);

            // PROBLEM: This fails - b is still here.
            assertNull(b);
            em.getTransaction().commit();

        } finally {
            if (em.getTransaction().isActive())
                em.getTransaction().rollback();
        }

    }
}


I have solved my problem. Really really simple - my initial code was almost right. I just had a syntax problem in the foreign key cascade. The attributes needed to be in brackets "()", I had overlooked that in the documentation. So the change I needed to do is:

@OneToOne
    @JoinColumn(
            foreignKey=@ForeignKey(
                    foreignKeyDefinition="FOREIGN KEY (ref2a) REFERENCES A (id) ON DELETE CASCADE"
                    )
            )
    private A ref2a;

Please notice the brackets around the two attributes.

This works, deleting an A object also cascades its linked B objects.

Thanks to everybody for your help!


Recommend

About Joyk


Aggregate valuable and interesting links.
Joyk means Joy of geeK