How can I get information from a junction table using JPA / EclipseLink?

I have the following multivalued mapping:




public class Student implements
{
    @Id
    @GeneratedValue
    private Integer xID;
      



@ManyToMany
@JoinTable(name = "x_y", 
           joinColumns = { @JoinColumn(name = "xID")},
           inverseJoinColumns={@JoinColumn(name="yID")})
private Set<Cat> cats;

      

}

public class Cat implements {@ I'd @GeneratedValue private Integer yID;

@ManyToMany
@JoinTable(name = "x_y", 
           joinColumns = { @JoinColumn(name = "yID")},
           inverseJoinColumns={@JoinColumn(name="xID")})
private Set<Student> students;

      

} code>

Please ignore object and property names, they are bogus and irrelevant. This compiles and works fine. I can also do this:




Entitymanager em = emf.createEntityManager();
      



em.getTransaction (). begin (); Student s = new Student (); Student s2 = new Student (); Cat c = new Cat (); em.persist (s); em.persist (s2); em.persist (c); s.getCats (). add (c); c.getStudents (). add (s2); em.getTransaction (). commit ();

My problem occurs when I return objects from the database.




em.getTransaction().begin();
Student s = em.find(Student.class, 2);
Cat c = em.find(Cat.class, 3);
      



if (c! = null) System.out.println (c.getYID () + ":" + c.getStudents ()); if (s! = null) System.out.println (s.getXID () + ":" + s.getCats ()); em.getTransaction (). commit ();

Printout:

3: {IndirectSet: not instantiated}

2: {IndirectSet: not instantiated}

This may be normal behavior. It just seems to me that when I return objects from the table, their sets related to other objects should be filled. I mean, since the join table looks like this:

X | Have

2 | 3

1 | 3

em.find (Cat.class, 3) should return a Cat object with set {1,2} for getStudents () and em.find (Student.class, 2) should return a Student object with set of {3} for getCats ( ).

Is there a way to make this possible?

Thanks BJ

0


a source to share


2 answers


Try adding @ManyToMany (cascade = CascadeType.ALL) to your Cat object to cascade your reads.

With proper cascades setup, you can change your save code:

Entitymanager em = emf.createEntityManager();

em.getTransaction().begin(); 
Student s = new Student(); 
Student s2 = new Student();
Cat c = new Cat();
// this should be c.setStudents(s2)
c.getStudents().add(s2); 
em.persist(c); 
em.getTransaction().commit(); 

      



To be honest, it is not entirely clear why you are trying to assign two sets of pupils to cats, you have to combine both sets into one and then add them to cats.

You may also need to explicitly specify your fetch type, @ManyToMany (fetch = FetchType.LAZY) or FetchType.EAGER.

0


a source


Perhaps the best example:




em.getTransaction().begin(); 
Student s = new Student(); 
Student s2 = new Student(); 
Cat c = new Cat(); 
em.persist(s); 
em.persist(s2);
em.persist(c); 
c.getStudents().add(s); 
c.getStudents().add(s2); 
em.getTransaction().commit(); 

      



and then try to say




Cat c2 = em.find(Cat.class,c.getYID());
Student s3 = em.find(Student.class,s.getXID());
System.out.println(c2.getYID() + ": " + c2.getStudents());
System.out.println(s3.getXID() + ": " + s3.getCats());

      





The above prints:

1: {[[Movie: movieID = 2], [Movie: movieID = 3]]}

2: {[]}

This doesn't make any sense to me, since the cat with id = 1 has a movie in its set with id = 2, but the movie with id = 2 doesn't have a cat in its set with id = 1. (Changing the cascade type didn't seem to have an effect on the results.)

Thank you very much for your reply.

Bj

0


a source







All Articles