many to many, added element gets removed
ben_utzer Aug 11, 2009 4:13 PMHi,
I cannot manage to update a Set of a many-to-many relation given the code below. The problem is that while the selected gruppe is added to the gruppen-Set on the update model phase it somehow gets lost when personHome.update() is called. This is happening during a long-running conversation.
The jUnit-test-method below executes without failure.
What am I missing here? Any help how to best deal with this situation would be appreciated.
Thanks,
Ben
Person.xhtml:
...
<s:fragment rendered="#{!personHome.edit}">
        <div>Klasse</div>
        <div>#{personHome.instance.schulklasseGruppe}</div>
</s:fragment>
 <s:fragment rendered="#{personHome.edit}">
        <label>Klasse</label>
        <h:selectOneMenu value="#{personHome.instance.schulklasseGruppe}">
                <s:selectItems var="gruppe" value="#{schulklasseGruppenQuery.dataModel}" label="#{gruppe.kennung}">
                </s:selectItems>
                <s:convertEntity />
        </h:selectOneMenu>
</s:fragment>
...
<h:commandButton action="#{personHome.update}" value="Update" />
...Person.java (personHome.instance):
@Entity
public class Person implements Serializable {
...
        @Transient
        private Gruppe schulklasseGruppe;
  
        @ManyToMany()
        @JoinTable(name = "gruppe_person", joinColumns = @JoinColumn(name = "person_id"), inverseJoinColumns = @JoinColumn(name = "gruppe_id"))
        private Set<Gruppe> gruppen = new HashSet<Gruppe>();
        
        public Gruppe getSchulklasseGruppe() {
                if(this.schulklasseGruppe == null && !this.gruppen.isEmpty()) {
                        for (Gruppe gruppe : this.gruppen) {
                                if(Boolean.TRUE.equals(gruppe.getGruppentyp().getSchulklasse())) {
                                        this.schulklasseGruppe = gruppe;
                                }
                        }
                }
                return schulklasseGruppe;
        }
        public void setSchulklasseGruppe(Gruppe schulklasseGruppe) {
                if(!this.gruppen.isEmpty()) {
                        Gruppe toRemove = null;
                        for (Gruppe gruppe : this.gruppen) {
                                if(Boolean.TRUE.equals(gruppe.getGruppentyp().getSchulklasse())) {
                                        toRemove = gruppe;
                                }
                        }
                        if(toRemove != null) {
                                this.gruppen.remove(toRemove);
                                toRemove.getPersonen().remove(this);
                        }
                }
                if(schulklasseGruppe != null) {
                        this.gruppen.add(schulklasseGruppe);
                        schulklasseGruppe.getPersonen().add(this);
                }
                this.schulklasseGruppe = schulklasseGruppe;
        }
...
}
Gruppe.java
@Entity
public class Gruppe implements Serializable {
        private String bezeichnung;
        @ManyToOne(fetch = FetchType.LAZY)
        @JoinColumn(name = "gruppentyp_id")
        private Gruppentyp gruppentyp;
        @Id
        @Column(name = "gruppe_id")
        @GeneratedValue(strategy = GenerationType.AUTO)
        private Integer id;
        @ManyToMany(mappedBy = "gruppen")
        private Set<Person> personen = new HashSet<Person>();
...
}
jUnit-Test:
       @Test
        public void testSetSchulklasseGruppe() {
                EntityManager em = getEntityManagerFactory().createEntityManager();
                em.getTransaction().begin();
                Person p = em.find(Person.class, new Integer(4218));
                int anzahlGruppen = p.getGruppen().size();
                Gruppe schulklasseGruppe = em.find(Gruppe.class, 13);
                p.setSchulklasseGruppe(schulklasseGruppe);
                em.flush();
                em.getTransaction().commit();
                p = em.find(Person.class, new Integer(4218));
                assertEquals(anzahlGruppen + 1, p.getGruppen().size());
                em.close();
        }