Spring Roo Avoiding ManyToMany cycles

323 Views Asked by At

I've got a simple @ManyToMany relationship I'm trying to capture, but I keep running into an infinite cycle problem.

I've got three classes kind of like this: Person, Issue, IssuePosition

Each person can have a position on any issue and can have positions against different issues. Positions are things like "for" "against" "neutral"

Issues are things like "increasing taxes" "building a new school"

Right now I've got in the Person class:

@OneToMany(cascade = CascadeType.ALL, orphanRemoval = true, mappedBy = "person", fetch = FetchType.EAGER)
@Fetch(FetchMode.SUBSELECT)
    private List<IssuePosition> issuePositions  = new ArrayList<IssuePosition>();

and in the Issue class:

@OneToMany(cascade = CascadeType.ALL, orphanRemoval = true, mappedBy = "issue", fetch = FetchType.EAGER)
    private List<IssuePosition> issuePositions  = new ArrayList<IssuePosition>();

in the IssuePosition class:

@ManyToOne(optional = true)
private Issue   issue;

@ManyToOne(optional = true)
private Person  person;

This causes a call to load the Person to load the IssuePositions which loads the Issues which loads the IssuePositions which loads the Person.

How do I stop this? I've removed the fetch=FetchType.EAGER but that didn't help

2

There are 2 best solutions below

0
On

This tutorial provides a good example of how to use the @ManyToMany annotation to map a relationship using a @JoinTable. Here's a slightly more complicated example.

0
On

I tried your implementation and it is working fine I have the following.

@Entity
public class IssuePosition {

    @Id
    private int id;

    @ManyToOne(optional = true)
    private Issue   issue;

    @ManyToOne(optional = true)
    private Person  person;

    @Override
    public String toString() {
        return "IssuePosition [id=" + id + "]";
    }

}



@Entity
public class Person {

    @Id
    private int id;

    @OneToMany(cascade = CascadeType.ALL, orphanRemoval = true, mappedBy = "person", fetch = FetchType.EAGER)
    @Fetch(FetchMode.SUBSELECT)
    private List<IssuePosition> issuePositions  = new ArrayList<IssuePosition>();

    @Override
    public String toString() {
        return "Person [id=" + id + ", issuePositions=" + issuePositions + "]";
    }


}


@Entity
public class Issue {

    @Id
    private int id;

    @OneToMany(cascade = CascadeType.ALL, orphanRemoval = true, mappedBy = "issue", fetch = FetchType.EAGER)
    private List<IssuePosition> issuePositions  = new ArrayList<IssuePosition>();

    @Override
    public String toString() {
        return "Issue [id=" + id + ", issuePositions=" + issuePositions + "]";
    }


}

And when I tried this:

EntityManagerFactory emf = Persistence.createEntityManagerFactory("jpaQuery");
        EntityManager em = emf.createEntityManager();

        Person p = em.find(Person.class, 1);
        System.out.println(p);

I obtained this

Hibernate: select person0_.id as id1_2_0_ from Person person0_ where person0_.id=? Hibernate: select issueposit0_.person_id as person3_2_2_, issueposit0_.id as id1_1_2_, issueposit0_.id as id1_1_1_, issueposit0_.issue_id as issue2_1_1_, issueposit0_.person_id as person3_1_1_, issue1_.id as id1_0_0_ from IssuePosition issueposit0_ left outer join Issue issue1_ on issueposit0_.issue_id=issue1_.id where issueposit0_.person_id=? Hibernate: select issueposit0_.issue_id as issue2_0_2_, issueposit0_.id as id1_1_2_, issueposit0_.id as id1_1_1_, issueposit0_.issue_id as issue2_1_1_, issueposit0_.person_id as person3_1_1_, person1_.id as id1_2_0_ from IssuePosition issueposit0_ left outer join Person person1_ on issueposit0_.person_id=person1_.id where issueposit0_.issue_id=? Hibernate: select issueposit0_.issue_id as issue2_0_2_, issueposit0_.id as id1_1_2_, issueposit0_.id as id1_1_1_, issueposit0_.issue_id as issue2_1_1_, issueposit0_.person_id as person3_1_1_, person1_.id as id1_2_0_ from IssuePosition issueposit0_ left outer join Person person1_ on issueposit0_.person_id=person1_.id where issueposit0_.issue_id=? Hibernate: select issueposit0_.issue_id as issue2_0_2_, issueposit0_.id as id1_1_2_, issueposit0_.id as id1_1_1_, issueposit0_.issue_id as issue2_1_1_, issueposit0_.person_id as person3_1_1_, person1_.id as id1_2_0_ from IssuePosition issueposit0_ left outer join Person person1_ on issueposit0_.person_id=person1_.id where issueposit0_.issue_id=? Hibernate: select issueposit0_.person_id as person3_2_2_, issueposit0_.id as id1_1_2_, issueposit0_.id as id1_1_1_, issueposit0_.issue_id as issue2_1_1_, issueposit0_.person_id as person3_1_1_, issue1_.id as id1_0_0_ from IssuePosition issueposit0_ left outer join Issue issue1_ on issueposit0_.issue_id=issue1_.id where issueposit0_.person_id in (select person1_.id from IssuePosition issueposit0_ left outer join Person person1_ on issueposit0_.person_id=person1_.id where issueposit0_.issue_id=?)

Person [id=1, issuePositions=[IssuePosition [id=1, issue=Issue [id=1]], IssuePosition [id=2, issue=Issue [id=2]], IssuePosition [id=3, issue=Issue [id=3]]]]

It seems is working, do you use getters or setters to print something, probably this makes the process enter in an infinite loop. Check that toString or any other method don't start a process to make a loop.

Image