Thursday, 23 August 2012

JPA Many-To-Many Relationships

This post illustrates many-to-many relationships between two classes. Don't forget to set the ownership on one side.
@Entity
@AutoProperty
public class ManyToManyA implements Serializable {

    @Id
    @GeneratedValue(strategy=GenerationType.AUTO)
    private long id;
 
    @Property(policy=PojomaticPolicy.NONE) 
    @ManyToMany(cascade=CascadeType.ALL)
    private Collection<ManyToManyB> listOfB
        = new ArrayList<ManyToManyB>();

    private String s;

    // Setters, Getters, Constructors, Pojomatic...

}


@Entity
@AutoProperty
public class ManyToManyB implements Serializable {

    @Id
    @GeneratedValue(strategy=GenerationType.AUTO)
    private long id;
 
    @Property(policy=PojomaticPolicy.NONE) 
    @ManyToMany(cascade=CascadeType.ALL, mappedBy="listOfB")
    private Collection<ManyToManyA> listOfA
        = new ArrayList<ManyToManyA>();
 
    private String s;

    // Setters, Getters, Constructors, Pojomatic...

}
The following:
ManyToManyA a1 = new ManyToManyA("AA1");
ManyToManyA a2 = new ManyToManyA("AA2");
ManyToManyA a3 = new ManyToManyA("AA3");
  
ManyToManyB b1 = new ManyToManyB("BB1");
ManyToManyB b2 = new ManyToManyB("BB2");

a1.getListOfB().add(b1);
b1.getListOfA().add(a1);
  
a3.getListOfB().add(b1);
b1.getListOfA().add(a3);
  
a2.getListOfB().add(b2);
b2.getListOfA().add(a2);
  
a3.getListOfB().add(b2);
b2.getListOfA().add(a3);
  
JPA.INSTANCE.save(a1);
JPA.INSTANCE.save(a2);
JPA.INSTANCE.save(a3);
JPA.INSTANCE.clear();
  
System.out.println("Retriving ManyToMany A's and their B's");

ManyToManyA retrA1
    = JPA.INSTANCE.get(ManyToManyA.class, a1.getId());
  
System.out.println(retrA1);
for (ManyToManyB origB : retrA1.getListOfB()) {
    ManyToManyB retrB
        = JPA.INSTANCE.get(
            ManyToManyB.class, origB.getId());
    System.out.println(retrB);
} System.out.println(" ");
  
ManyToManyA retrA2
    = JPA.INSTANCE.get(ManyToManyA.class, a2.getId());
  
System.out.println(retrA2);
for (ManyToManyB origB : retrA2.getListOfB()) {
    ManyToManyB retrB
        = JPA.INSTANCE.get(
            ManyToManyB.class, origB.getId());
    System.out.println(retrB);
} System.out.println(" ");
  
ManyToManyA retrA3
    = JPA.INSTANCE.get(ManyToManyA.class, a3.getId());
  
System.out.println(retrA3);
for (ManyToManyB origB : retrA3.getListOfB()) {
    ManyToManyB retrB
        = JPA.INSTANCE.get(
            ManyToManyB.class, origB.getId());
    System.out.println(retrB);
} System.out.println(" ");
  
System.out.println("Retriving ManyToMany B's and their A's");
  
ManyToManyB retrB1
= JPA.INSTANCE.get(ManyToManyB.class, b1.getId());
  
System.out.println(retrB1);
for (ManyToManyA origA : retrB1.getListOfA()) {
    ManyToManyA retrA
        = JPA.INSTANCE.get(
            ManyToManyA.class, origA.getId());
    System.out.println(retrA);
} System.out.println(" ");
  
ManyToManyB retrB2
= JPA.INSTANCE.get(ManyToManyB.class, b2.getId());
  
System.out.println(retrB2);
for (ManyToManyA origA : retrB2.getListOfA()) {
    ManyToManyA retrA
        = JPA.INSTANCE.get(
            ManyToManyA.class, origA.getId());
    System.out.println(retrA);
} System.out.println(" ");
Generates:
Retriving ManyToMany A's and their B's
ManyToManyA{id: {1}, s: {AA1}}
ManyToManyB{id: {1}, s: {BB1}}
 
ManyToManyA{id: {3}, s: {AA2}}
ManyToManyB{id: {2}, s: {BB2}}
 
ManyToManyA{id: {2}, s: {AA3}}
ManyToManyB{id: {1}, s: {BB1}}
ManyToManyB{id: {2}, s: {BB2}}
 
Retriving ManyToMany B's and their A's
ManyToManyB{id: {1}, s: {BB1}}
ManyToManyA{id: {1}, s: {AA1}}
ManyToManyA{id: {2}, s: {AA3}}
 
ManyToManyB{id: {2}, s: {BB2}}
ManyToManyA{id: {2}, s: {AA3}}
ManyToManyA{id: {3}, s: {AA2}}
The above examples are available from Github in the JPA directory. They rely on Pojomatic too. Some errors messages will be displayed because of a known and harmless issue.