2015-08-06 8 views
11

Ich habe 3 Klassen entsprechend 3 Tabellen V, und P. D hatte einen FK zu V (FK_V) und wird mit der OneToMany-Beziehung verbunden. Auch ihre Ausgänge eine vierte Tabelle V_D_P, die die Beziehung dieser V, und P hat.Hibernate versucht, das gleiche Objekt zweimal zu halten

Es folgt, was das Datenmodell für diese aussieht:

@Entity 
@Table(name = "V")             
public class V { 

    @Id 
    @GeneratedValue(strategy = GenerationType.SEQUENCE) 
    @Column(name = "ID") 
    private Long id; 

    @OneToMany(cascade=CascadeType.ALL) 
    @JoinColumn(name = "FK_V", referencedColumnName="Id", nullable = false) 
    private Set<D> d; 

    @OneToMany(cascade=CascadeType.ALL) 
    @JoinColumn(name = "FK_V", referencedColumnName="Id", nullable = false) 
    private Set<V_D_P> vdp; 

    //Getters Setters etc. 
} 


@Entity 
@Table(name = "V_D_P") 
public class V_D_P { 

     @Id 
     @GeneratedValue(strategy = GenerationType.SEQUENCE) 
     @Column(name = "ID") 
     private Long id; 

    @ManyToOne(cascade=CascadeType.ALL) 
    @JoinColumn(name = "FK_D", nullable = false) 
    private D d; 

    @ManyToOne(cascade=CascadeType.ALL) 
    @JoinColumn(name = "FK_P", nullable = false) 
    private P p; 

    //Getters Setters etc.  
} 

@Entity 
@Table(name = "D")             
public class D { 
     @Id 
     @GeneratedValue(strategy = GenerationType.SEQUENCE) 
     @Column(name = "ID") 
     private Long id; 

    //Getters Setters etc. 
} 

@Entity 
@Table(name = "P")             
public class P { 

     @Id 
     @GeneratedValue(strategy = GenerationType.SEQUENCE) 
     @Column(name = "ID") 
     private Long id; 

    //Getters Setters etc. 
} 

Jetzt möchte ich V, D und P zusammen mit ihrer Beziehung bestehen. Ich bin

V v = new V(); 

D d = new D(); 
Set<D> dSet = new HashSet<>(); 
dSet.add(d); 
v.setD(dSet); // Adding d to V ....(1) 

P p = new P(); 
V_D_P vdp = new V_D_P(); 

vdp.setD(d); // Adding d to V_D_P ....(2) 
vdp.setP(p); 

Set<V_D_P> vdpSet = new HashSet<V_D_P>(); 
vdpSet.add(vdp); 
v.setVdp(vdpSet); 

entityManager.persist(v); 

Jetzt können Sie die ich sehe, bin Zugabe des gleichen d Objekt zweimal. Einmal nach P und einmal nach V_D_P. Da es sich jedoch um dieselben Objekte handelt, sollte nur ein einziges davon bestehen bleiben. Auf der Grundlage der Ruhezustandslogs sehe ich jedoch, dass Hibernate versucht, zwei verschiedene Objekte einzufügen.

Ich sehe auch die folgende Ausnahme: ORA-00001: eindeutige Einschränkung

Gibt es eine Möglichkeit überwintern zu lassen, dass diese die gleichen Objekte sind und sie nur einmal Persis?

+1

Ich konnte Ihr Problem nicht reproduzieren; es wird nur eine insert-Anweisung für "D" erzeugt. Sind alle Anmerkungen aus 'javax.persistence. *' Paket? –

+1

@DraganBozanovic: Ja. Beide Annotationen stammen aus dem Paket javax.persistence. *. Können Sie sich anpassen, dass Sie das gleiche obj zweimal hinzufügen (wie dSet.add (d); & vdp.setD (d);) und dann versuchen, beide zu erhalten? –

+1

Ja, ich habe den von Ihnen geposteten Code kopiert und eingefügt. [Hier] (http://pastie.org/10341717) ist der Hibernate generierte SQL; Ich habe es mit H2-Datenbank versucht ('org.hibernate.dialect.H2Dialect'). Welchen Dialekt benutzen Sie und können Sie das von Hibernate generierte SQL in Ihrem Fall posten? –

Antwort

4

Objekte werden durch ID eindeutig identifiziert. Daher müssen sie die gleiche ID haben.

  • Entweder stellen die ID vor,
  • oder anhalten einmal und aktualisieren d Objekt vor den anderen Speichern (so hat es die ID-Set).
1

Versuchen Sie save() anstelle von persist(). Wie in this post erwähnt, aktualisiert persist nicht unbedingt sofort die ID des Objekts. Das bedeutet, dass der Ruhezustand das Objekt "d" zweimal erreichen kann, wenn er das Objektdiagramm durchläuft. Beide Male könnte es sagen "die ID ist null, ich muss eine neue einfügen!".

Scheinbar ist dieses Verhalten nicht gut definiert, so dass es nicht in allen Fällen passieren kann.

1

Benötigen Sie wirklich das VDP.d-Feld: können Sie nicht einfach eine bidirektionale (gemappte) Beziehung zwischen V und V (D) P verwenden (V (D) P hätte ein av-Feld) und einfach navigieren V (D) Pvd?

Verwandte Themen