[
Date Prev][
Date Next][
Thread Prev][
Thread Next][
Date Index][
Thread Index]
[
List Home]
Re: [eclipselink-users] ManyToMany did not persist in both directions
|
Hello,
From the sounds of it, you have a bi-directional M:M, and are only
populating one of the collection types. When the one that is populated
is the side that owns the relationship, you get the join table inserts
as expected. When the other collection is populated, and the collection
that owns the relationship is left blank, you don't. This is as designed.
The specification requires both sides to be maintained. So if the
application is populating one side of the relationship, it should (must)
populate the other side to keep it consistent with what will (or is
desired to) be in the database. When they are inconsistent, you get
inconsistent results. In this case, the state of the two collections do
not match, and the one that owns the relationship is taken to represent
the actual values for the database. Allowing changes to both sides to
be reflected into the database would lead to potential duplicate results
- for instance when an application correctly maintains both sides of the
relationship, an entry to the join table might get duplicated. It is
also then impossible to tell what should happen when a reference is
removed from one collection but left in the other.
Best Regards,
Chris
farisola@xxxxxx wrote:
Hello,
using annotation @ManyToMany did not persist
in both directions:
I have to n:m related tables, LEHRER and SCHUELER
That results in 3 database tables:
1. LEHERER
2. SCHUELER
3. LEHERER_SCHUELER
At the end you can find the two corresponding entity classes
and the two test cases.
Both entites contain the neccessary @ManyToMany annotations, see below.
The entity LEHERER contains the @JoinTable annotation, the entity SCHUELER not.
The problem:
If I persist a new LEHRER entity that contains some SCHUELER,
then all three tables will have the corresponding entries.
But if I persist a new SCHUELER entity that contains some LEHRER ,
then ONLY the tables SCHUELER and LEHRER will have the corresponding entries,
but the table LEHERER_SCHUELER will be ignored.
<<<
I think the persistence should work in both directions independent of the place,
where the @JoinTable annotation is placed.
All is running on a Oracle 10g Database.
Did someone have an idea, what is wrong?
// +-----------------------------------------------------------------------+
@Entity
@Table(name="LEHRER")
public class Lehrer extends ZAdminEntity implements Serializable {
private static final long serialVersionUID = 1L;
private long pk;
private String lehrername;
private List<Schueler> schuelers;
public Lehrer() { }
@Id
@SequenceGenerator(name="LEHRER_PK_GENERATOR", sequenceName="SEQ_LEHRER")
@GeneratedValue(strategy=GenerationType.SEQUENCE, generator="LEHRER_PK_GENERATOR")
@Column(unique=true, nullable=false, precision=22)
public long getPk() {
return this.pk;
}
public void setPk(long pk) {
this.pk = pk;
}
@Column(nullable=false)
public String getLehrername() {
return this.lehrername;
}
public void setLehrername(String lehrername) {
this.lehrername = lehrername;
}
//bi-directional many-to-many association to Schueler
@ManyToMany(cascade={CascadeType.ALL}, fetch=FetchType.EAGER)
@JoinTable(
name="LEHRER_SCHUELER"
, joinColumns={@JoinColumn(name="LEHRER_PK", nullable=false)}
, inverseJoinColumns={@JoinColumn(name="SCHUELER_PK", nullable=false)}
)
public List<Schueler> getSchuelers() {
return this.schuelers;
}
public void setSchuelers(List<Schueler> schuelers) {
this.schuelers = schuelers;
}
}
// +-----------------------------------------------------------------------+
@Entity
@Table(name="SCHUELER")
public class Schueler extends ZAdminEntity implements Serializable {
private static final long serialVersionUID = 1L;
private long pk;
private String schuelername;
private List<Lehrer> lehrers;
public Schueler() {}
@Id
@SequenceGenerator(name="SCHUELER_PK_GENERATOR", sequenceName="SEQ_SCHUELER")
@GeneratedValue(strategy=GenerationType.SEQUENCE, generator="SCHUELER_PK_GENERATOR")
@Column(unique=true, nullable=false, precision=22)
public long getPk() {
return this.pk;
}
public void setPk(long pk) {
this.pk = pk;
}
@Column(nullable=false)
public String getSchuelername() {
return this.schuelername;
}
public void setSchuelername(String schuelername) {
this.schuelername = schuelername;
}
//bi-directional many-to-many association to Lehrer
@ManyToMany(mappedBy="schuelers", cascade={CascadeType.ALL}, fetch=FetchType.EAGER)
public List<Lehrer> getLehrers() {
return this.lehrers;
}
public void setLehrers(List<Lehrer> lehrers) {
this.lehrers = lehrers;
}
}
// +-----------------------------------------------------------------------+
@Test
/**
* Is working!
*/
public void lehrerschueler() {
EntityManagerFactory emf = getEMF();
EntityManager em = emf.createEntityManager();
Lehrer lehrer = this.getNewLehrer();
Schueler schueler = this.getNewSchueler();
ArrayList <Schueler> list = new ArrayList <Schueler> ();
list.add(schueler);
lehrer.setSchuelers(list);
em.getTransaction().begin();
try {
// persist the lehrer
em.persist(lehrer);
em.getTransaction().commit();
} catch (Exception e) {
e.printStackTrace();
Assert.fail(e.getMessage());
}
}
// +-----------------------------------------------------------------------+
@Test
/**
* IS NOT working!
*/
public void schuelerlehrer() {
EntityManagerFactory emf = getEMF();
EntityManager em = emf.createEntityManager();
Schueler schueler = this.getNewSchueler();
Lehrer lehrer = this.getNewLehrer();
ArrayList <Lehrer> list = new ArrayList <Lehrer> ();
list.add(lehrer);
schueler.setLehrers(list);
em.getTransaction().begin();
try {
// persist the schueler
em.persist(schueler);
em.getTransaction().commit();
} catch (Exception e) {
e.printStackTrace();
Assert.fail(e.getMessage());
}
}
// +-----------------------------------------------------------------------+
greetings Farisola