The problem

Recently I’ve stumbled upon a weird snippet of code in a project I’ve been involved into. The previous developer set some entity relations to null before deleting it. I was wondering why he did so. The project uses Hibernate.

So I decided to investigate this.

Here are the components (these classes are made up only for this case) :

@Table(name = "artists")
public class Artist {

    private String artistName;

    @OneToMany(cascade = CascadeType.ALL)
    @JoinColumns(@JoinColumn(name = "artistId"))
    private Set<Album> albums = new HashSet<Album>();

    // Id and getters/setters not shown for the sake of brevity.

@Table(name = "albums")
public class Album {

    private String name;

And here is a test case :

@ContextConfiguration(locations = {"classpath:applicationContext.xml"})
@TestExecutionListeners({ DependencyInjectionTestExecutionListener.class,
        CleanDataSetTestExecutionListener.class })
public class ArtistRepositoryTest implements ApplicationContextAware {

    private ArtistRepository dao;

    public void testDelete() {
        Artist artist = dao.findByArtistName("Led Zeppelin");


        assertEquals("Number of artists in table =>", 0, countRowsInTable("artists"));
        assertEquals("Number of albums in table =>", 1, countRowsInTable("albums"));

With the flat xml dataset :

<?xml version="1.0" encoding="UTF-8"?>
    <artists id="1" artistName="Led Zeppelin"/>
    <albums id="1" name="Physical Graffiti" artistId="1"/>

Note that I’m not executing this test in a transaction, the transaction demarcation is on the findByArtistName() method.

I’ve launched this test case with both OpenJPA (2.2.1) and Hibernate (3.6.9)

The results


With OpenJPA, I get the following :

java.lang.AssertionError: Number of albums in table => expected:<1> but was:<0>
    at org.junit.Assert.failNotEquals(
    at org.junit.Assert.assertEquals(
    at org.junit.Assert.assertEquals(
    at be.codinsanity.sandbox.db.ArtistRepositoryTest.testDelete(

This seems normal : since I delete the artist and there is a CascadeType.ALL associated to albums, it alse deletes the latter, even though I set it null.

Now let’s try with Hibernate


Here’s a completely different story since the test pass ! So it means that setting the albums collection to null really has an impact on the behavior. Better, if I don’t change the albums field, the test don’t pass anymore, which is what I was expected to see at first.

So it seems Hibernate updates the state of the entity before deleting it in the database. Is it a correct behavior ? Can we change this with a property ?


I must say that I’m very intrigued by this behavior. I must investigate further in order to have the final word on this, but time lacks. If someone has the answer to this, please leave a comment.