Joe Essey
Joe Essey

Reputation: 3527

JPA @ManyToMany associations seem to only be working 1 way

I've got the following association defined:

public class Location
...
@ManyToMany(mappedBy="locations")
    private List<KMLFolder> kmlFolderList;

public class KMLFolder
...
@ManyToMany(cascade=CascadeType.ALL)
    @JoinTable(name="LOCATION_KMLFOLDER",
        joinColumns={@JoinColumn(name="KMLFOLDER_ID", referencedColumnName="ID")},
        inverseJoinColumns={@JoinColumn(name="LOCATION_ID", referencedColumnName="ID")}
            )
    private List<Location> locations = new ArrayList<Location>();

Here is a unit test. The first 3 assertions pass but the last one fails:

@Test
@Transactional
public void thatFolderLocationAssociationTableIsWorking() {
    Location l1 = new DomesticLocation();
    l1.setDeptName("Test name 1");
    Location l2 = new DomesticLocation();
    l2.setDeptName("Test name 2");

    KMLFolder k1 = new KMLFolder();
    k1.setName("Test name 1");

    List<Location> locations = new ArrayList<Location>();
    locations.add(l1);
    locations.add(l2);
    k1.setLocations(locations);

    kmlFolderServiceImpl.save(k1);

    assertEquals("Test name 1", kmlFolderServiceImpl.find(1L).getLocations().get(0).getDeptName());
    assertEquals("Test name 2", kmlFolderServiceImpl.find(1L).getLocations().get(1).getDeptName());
    assertNotNull(locationServiceImpl.findAll().get(0));

    //Failing Assertion
    assertNotNull(locationServiceImpl.find(1L).getKmlFolderList());

}

Any thoughts why this may not be persisting correctly? Thanks.

Upvotes: 0

Views: 77

Answers (1)

JB Nizet
JB Nizet

Reputation: 691635

All the code is executed inside a single transaction. The Hibernate session, and thus the first-level cache, is thus unique for all the code in the test. Your code initializes one side of the association without initializing the other. You thus create an incoherent object graph, that is stored in the first level cache.

When using Hibernate to load the entities using a finder, Hibernate returns the incoherent entities that are in the cache. If you had one transaction for saving, and another one to get back the entities, Hibernate would use a new, empty cache for the second transaction, and would populate the entities, in a coherent way, from the data found in the tables.

Upvotes: 1

Related Questions