2010-08-09 72 views
6

我有一個應用程序,我試圖在使用Hibernate作爲我的JPA提供程序的兩個實體之間實現ManyToMany關係。由JPA產生的空連接表ManyToMany

我想要的例子是單向的,其中一個攝像頭可以有多個鏡頭,而Lense可以適合多個攝像頭。

以下是我的實體類...(只是粘貼它的相關部分)

攝像頭:

@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>(); 

    ... 
} 

鏡頭:

@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; 

    ... 
} 

在測試情況下,我嘗試堅持像這樣的相機實例...

@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); 
} 

持久發生成功,並且沒有Hibernate引發的錯誤/異常。但是,與預期相反,JoinTable中沒有創建一行(在這種情況下爲CAMERA_LENS)。僅在每個鏡頭和相機表格中創建一行,從而不符合ManyToMany的目的。但是,DDL是爲連接表生成的,它也是創建的,但它只是沒有任何記錄。

任何援助或指針將不勝感激。

回答

5

我發現了這個問題。這有點奇怪。我用的是DAO類有一個類級別的註釋:

@Transactional(readOnly=true) 

生成的SQL是

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

而且它仍然保存2個實體,但沒有保存或將數據插入到連接表。

我添加的方法級別的註釋的時刻:

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

一切都變成了要罰款,以及數據確實被插入到連接表。在這種情況下產生的新的sql語句是......

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 (?, ?) 

有點奇怪仍然沒有成交傳播史戰略保存的數據爲2個表,但一旦傳播史的策略被賦予,一切都變成了要罰款。

另一個有趣的觀察是,我嘗試在方法級別上將傳播策略作爲強制(以檢查是否存在導致第一個錯誤情況的事務),但是該方法拋出了表明沒有事務存在的異常,數據仍保存在2個表格中。

希望可以幫助別人進一步...

+2

在我的情況下,這並沒有幫助。有什麼可以幫助我們刷新會話......(我仍然不明白爲什麼需要這樣做,因爲在事務內部看到的其他收集更新,只是這個中間表需要更新的地方沒有看到。 – 2012-04-16 21:16:05

+0

我認爲@Transactional(readOnly = true)可能仍然有一個默認傳播,它是REQUIRED,它會啓動一個tx。我遇到了同樣的問題,使用@Transactional(progpagation = REQUIRED,readOnly = true)沒有插入到連接表中。調用flush爲@Adres建議工作,但也刪除了readOnly – ams 2012-09-16 14:46:57