2010-08-09 2 views
6

Ich habe eine Anwendung, in der ich versuche, ManyToMany-Beziehung zwischen 2 Entitäten mit Hibernate als JPA-Provider zu implementieren.Leere Join Tabelle aus JPA ManyToMany

Das Beispiel, das ich versuche, ist ein unidirektionales, wobei eine Kamera mehrere Objektive haben kann und Lense in mehrere Kameras passen kann.

Folgende ist meine Entitätsklasse ... (einfach den entsprechenden Teil des Einfügen)

Kamera:

@Entity 
@Table(name = "CAMERAS") 
public class Camera implements Serializable { 
    @Id 
    @GeneratedValue(strategy = GenerationType.AUTO) 
    @Column(name = "CAM_ID", nullable = false) 
    private Long camId; 

    @Column(name="CAMERA_BRAND") 
    private String cameraBrand; 

    @ManyToMany(cascade={CascadeType.PERSIST, CascadeType.MERGE},fetch=FetchType.EAGER) 
    @JoinTable(name="CAMERA_LENS",[email protected](name="CAM_ID"),[email protected](name="LENS_ID")) 
     private Set<Lens> lenses = new HashSet<Lens>(); 

    ... 
} 

Objektiv:

@Entity 
@Table(name = "LENSES") 
public class Lens implements Serializable {   
    @Id 
    @GeneratedValue(strategy = GenerationType.AUTO) 
    @Column(name = "LENS_ID", nullable = false) 
    private Long lensId; 

    @Column(name="LENS_NAME") 
    private String name; 

    ... 
} 

Im Test-Fall I versuchen Sie, die Kamera-Instanz so zu halten ...

@Test 
public void test_saveCameraLenseManyToMany() { 
    Camera cam = new Camera(); 
    cam.setCameraBrand("Nikon"); 
    Set<Camera> cameras = new HashSet<Camera>(); 
    cameras.add(cam); 

    Set<Lens> lenses = new HashSet<Lens>(); 
    Lens lens1 = new Lens(); 
    lens1.setName("WideAngle"); 
    lenses.add(lens1); 

    cam.setLenses(lenses); 

    // concreteDAO.saveLens(lens1); 
    concreteDAO.saveCamera(cam); 
} 

Die Persistenz wird erfolgreich ausgeführt, und es wird kein Fehler/Ausnahmefehler von Hibernate ausgelöst. Entgegen der Erwartung wird in der JoinTable (in diesem Fall CAMERA_LENS) jedoch keine Zeile erstellt. Eine Zeile wird nur in den Tabellen Lens und Camera erstellt und dient somit nicht dem Zweck von ManyToMany. Die DDL wird jedoch für die Join-Tabelle generiert, und sie wird ebenfalls erstellt, enthält jedoch keine Datensätze.

Jede Hilfe oder Hinweise würden sehr geschätzt werden.

Antwort

5

Ich habe das Problem gefunden. Es ist ein bisschen komisch. Die DAO-Klasse, die ich benutze hatte eine Klassenstufe Kommentierung:

@Transactional(readOnly=true) 

Die SQL erzeugt wurde

Hibernate: insert into CAMERAS (CAMERA_BRAND) values (?) 
Hibernate: insert into LENSES (LENS_NAME) values (?) 
Hibernate: insert into LENSES (LENS_NAME) values (?) 

Und es immer noch die 2 Einheiten gespeichert, aber nicht Daten in die Verbindung speichern oder einfügen Tabelle.

In dem Moment habe ich eine Methode Ebene Annotation hinzugefügt:

@Transactional(readOnly = false, propagation = Propagation.REQUIRES_NEW) 

alles erwies sich als in Ordnung zu sein, und die Daten wurden in der Tat in die Tabelle beitreten eingefügt. Die neuen SQLs in diesem Fall generiert wird, waren ...

Hibernate: insert into CAMERAS (CAMERA_BRAND) values (?) 
Hibernate: insert into LENSES (LENS_NAME) values (?) 
Hibernate: insert into LENSES (LENS_NAME) values (?) 

Hibernate: insert into CAMERAS_LENSES (CAM_ID, LENS_ID) values (?, ?) 
Hibernate: insert into CAMERAS_LENSES (CAM_ID, LENS_ID) values (?, ?) 

Kinda seltsam immer noch, dass keine Transaktion propogation Strategie Daten in zwei Tabellen gespeichert, aber sobald die propogation Strategie in Ordnung zu sein, alles drehte gegeben wurde, aus. Eine weitere interessante Beobachtung ist, dass ich versucht habe, die Propagierungsstrategie als VERBINDLICH auf Methodenebene zu setzen (um zu prüfen, ob es eine Transaktion gab, die zum ersten und fehlerhaften Fall führte), aber die Methode gab eine Ausnahme aus, die anzeigt, dass keine Transaktion existierte , noch wurden die Daten in den 2 Tabellen gespeichert.

Hoffe, dass jemand weiter hilft ...

+2

In meinem Fall, das hat nicht geholfen. Was half, war die Sitzung zu leeren ... (Ich verstehe immer noch nicht, warum dies nötig war, da andere Sammlungsaktualisierungen in der Transaktion zu sehen waren. Gerade diese, in der die Zwischentabelle eine Aktualisierung benötigte, wurde nicht gesehen. –

+0

Ich denke, @Transactional (readOnly = true) könnte immer noch eine Standardausbreitung haben, die ERFORDERLICH ist, die ein TX starten würde.Ich stieß auf das gleiche Problem und bekam mit @Transactional (progpagation = REQUIRED, readOnly = true) nicht in die Join-Tabelle eingefügt. Calling Flush wie @Adres schlägt funktioniert, aber auch das Entfernen ReadOnly – ams

Verwandte Themen