2012-11-05 8 views
6

Meine Frage an diesem ziemlich ähnlich ist einer Hibernate Bi-Directional ManyToMany Updates with Second Level cacheHibernate Bidirektionale viele zu viele Vereinigung schafft Duplikate

I Klasse haben wie unten

@Cache(usage = CacheConcurrencyStrategy.TRANSACTIONAL) 
@Entity 
public class A{ 
    private int id; 
    private List<B> listB; 

    ... 
    @Cache (usage = CacheConcurrencyStrategy.TRANSACTIONAL) 
    @ManyToMany(cascade = {CascadeType.PERSIST, CascadeType.MERGE}, targetEntity = B.class) 
    @JoinTable(name = "A_B", joinColumns = { @JoinColumn(name = "a_id") }, 
     inverseJoinColumns = { @JoinColumn(name = "b_id") }) 
    public List<B> getListB() { 
     return listB ; 
    } 
} 

@Cache (usage = CacheConcurrencyStrategy.TRANSACTIONAL) 
@Entity 
public class B{ 
    private int id; 
    private List<A> listA; 

    @ManyToMany(cascade = {CascadeType.PERSIST, CascadeType.MERGE}, targetEntity = A.class) 
    @JoinTable(name = "A_B", joinColumns = { @JoinColumn(name = "b_id") }, inverseJoinColumns = { @JoinColumn(name = "a_id") }) 
    public List<a> getListA() { 
     return listA ; 
    } 

    public void addToA(A a) { 
     a.getListB().add(this); 
    } 
} 

gezeigt Was viele Beziehung in einer von vielen erwartet, ich habe beide Seiten der bidirektionalen Beziehung aktualisiert.

Jetzt ist das Problem, das ich gegenüberstelle, doppelte Einträge Popup, wenn ich versuche, ein Element in der Sammlung hinzuzufügen/zu aktualisieren. Im Folgenden ist der Code, den ich an das Unternehmen beharren verwenden ...

b.getA().clear() ; 
... 
... 
b.getListA().add(A) ; 
b.addToA(A) ; 
em.saveOrUpdate(b) ; 

Im Folgenden werden die von Hibernate gefeuert Abfragen, die aus den Protokollen erhalten werden.

delete from A_B where b_id=? 

insert into A_B (b_id, a_id) values (?, ?) 
insert into A_B (b_id, a_id) values (?, ?) 

delete from A_B where a_id=? 

insert into A_B (a_id, b_id) values (?, ?) 
insert into A_B (a_id, b_id) values (?, ?) 
insert into A_B (a_id, b_id) values (?, ?) 
insert into A_B (a_id, b_id) values (?, ?) 

Wohin gehe ich hier falsch? Wie werden die Duplikate entfernt, die eingefügt werden? Cache wird ordnungsgemäß geleert, aber die doppelten Einträge sind das einzige Problem!

Antwort

10

Dies ist ein Klassiker!

Das Problem ist, dass beide Ihre Mappings Besitzer sind, wenn einer der Besitzer sein sollte, und einer sollte invers sein. Da beide Eigentümer sind, führen Änderungen an beiden zu Einfügungen in die Datenbank. Bei einem Besitzer und einer Umkehrung gibt es nur einen Satz von Einfügungen.

sollten Sie in der Lage sein, neu zu schreiben B::getListA wie:

@ManyToMany(cascade = {CascadeType.PERSIST, CascadeType.MERGE}, mappedBy = "listB") 
public List<A> getListA() 

Und alles funktioniert hat.

Beachten Sie, dass nur die Eigentümerseite als @JoinTable Annotation. In der Regel wird jedes gegebene Bit der Datenbank in genau einem Platz in einer JPA-Anwendung zugeordnet. Wenn Sie jemals etwas zweimal zuordnen, sollten Sie einen langen Blick darauf werfen, ob es einen besseren Weg dafür gibt.

Übrigens brauchen Sie nicht die targetEntity Attribute; Ein JPA-Anbieter kann das aus den Generika herausarbeiten.

+3

Großartig! Mit dem Attribut mappedBy informieren wir Hibernate darüber, dass es sich um die Owner-Tabelle und die Join-Konfiguration der Entitäten handelt. Ist mein Verständnis richtig? – Venkat

+2

Ja, das ist es genau. –

+0

Irgendeine Idee, warum Sie immer noch doppelte Einfügungen erhalten, wenn Sie das mappedBy-Setup richtig vorgenommen haben? In meinem Fall verwende ich Feldzugriff statt Methodenzugriff. Könnte das ein Problem sein? – JBCP

Verwandte Themen