The setup is traditional Spring + Hibernate (4.3) app.
I have unidirectional relationship between two entities A
and B
(B
is the owner of the relationship). Unlikely all examples I found, my parent entity A
is not the owner of the relationship.
Here is how they look:
@Entity
@Table(name = "a")
public class A {
@Id
@GeneratedValue(generator = "system-uuid")
@GenericGenerator(name = "system-uuid", strategy = "uuid2")
@Type(type = "pg-uuid") private UUID id;
/* Some other fields non-referring B */
/* rest omitted for simplicity */
}
@Entity
@Table(name = "b")
public class B {
@Id
@Type(type = "pg-uuid")
private UUID id;
@MapsId
@ManyToOne()
@OnDelete(action = OnDeleteAction.CASCADE)
private A a;
@Embedded
private SomeEmbeddable someEmbeddable;
/* rest omitted for simplicity */
}
Now when I delete A
I want B
to be also deleted. There is the first question:
Q1: How Hibernate will handle the cascading delete since
A
dosn't know of the existence ofB
(the unidirectional relationshipB
toA
)? Will it be able to deleteB
and should it be able to?
Thinking about it I created the following test:
@RunWith(SpringJUnit4ClassRunner.class)
@ContextConfiguration(classes = {PersistenceConfig.class})
@Rollback(false)
@Transactional
@FixMethodOrder(MethodSorters.NAME_ASCENDING)
public class Test {
@PersistenceContext
private EntityManager em;
private static UUID aId = null;
@Test
public void test1() throws Exception {
/* creating entities */
A a = new A();
A savedA = em.merge(a);
B b = new B();
b.setA(A);
B savedB = em.merge(b);
/* check entities are saved and have IDs */
assertNotNull("Saved A should not be null.", savedA);
assertNotNull("Saved A's ID should not be null.", savedA.getId());
assertNotNull("Saved B should not be null.", savedB);
assertNotNull("Saved B's ID should not be null.", savedB.getId());
assertEquals("A and B IDs should be equal", savedA.getId(), savedB.getId());
/* save the ID for use in the second test method */
aId = savedA.getId();
/* delete the parent entity (A) */
em.remove(savedA);
}
/* In another test to force different transaction */
@Test
public void test2() throws Exception {
/* find entities */
A foundA = em.find(A.class, aId);
B foundA = em.find(B.class, aId);
assertNull("A should be null after it was deleted.", foundA);
/* What about B ?!? */
assertNull("Should B also gets deleted after A is deleted?", foundB);
}
}
What happens is the first test test1()
passes and the second test2
fails on the first assert "A should be null after it was deleted."
.
Q2: Why A does not get deleted?
Interestingly if I ignore (@Ignore
) the second test and remove the last line em.remove(savedA);
then the records are persisted in the DB. Then I get the ID of A
and hard-code it in the second test it passes successfully. I am misunderstanding something here.
P.S. I don't want to have A
referencing B
.
Aucun commentaire:
Enregistrer un commentaire