由JPA ManyToMany生成的空连接表

Pai*_*aiS 6 java orm many-to-many jpa

我有一个应用程序,我试图使用Hibernate作为我的JPA提供程序在2个实体之间实现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",joinColumns=@JoinColumn(name="CAM_ID"),inverseJoinColumns=@JoinColumn(name="LENS_ID"))
        private Set<Lens> lenses = new HashSet<Lens>();

    ...
}
Run Code Online (Sandbox Code Playgroud)

镜片:

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

    ...
}
Run Code Online (Sandbox Code Playgroud)

在测试用例中,我尝试像这样坚持Camera实例......

@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);
}
Run Code Online (Sandbox Code Playgroud)

持久性成功发生,并且Hibernate没有抛出错误/异常.但是,与期望相反,JoinTable中不会创建行(在本例中为CAMERA_LENS).仅在每个镜头和相机表中创建一行,因此不能满足ManyToMany的目的.但是,为连接表生成DDL并创建它,但只是它没有任何记录.

任何帮助或指示将不胜感激.

Pai*_*aiS 5

我发现了这个问题.这有点奇怪.我使用的DAO类具有类级别注释:

@Transactional(readOnly=true)
Run Code Online (Sandbox Code Playgroud)

生成的sql是

Hibernate: insert into CAMERAS (CAMERA_BRAND) values (?)
Hibernate: insert into LENSES (LENS_NAME) values (?)
Hibernate: insert into LENSES (LENS_NAME) values (?)
Run Code Online (Sandbox Code Playgroud)

它仍然保存了2个实体,但没有将数据保存或插入到连接表中.

我添加方法级别注释的那一刻:

@Transactional(readOnly = false, propagation = Propagation.REQUIRES_NEW)
Run Code Online (Sandbox Code Playgroud)

一切都很好,数据确实插入到连接表中.在这种情况下生成的新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 (?, ?)
Run Code Online (Sandbox Code Playgroud)

有点奇怪的是,没有交易传播策略将数据保存到2个表中,但是一旦给出了传播策略,一切都证明是好的.

另一个有趣的观察是我尝试将propogation策略作为MANDATORY放在方法级别(检查是否存在导致第一个和错误情况的事务),但是该方法引发了一个异常,表明没有事务存在,仍然是数据被保存到2个表中.

希望能进一步帮助某人......

  • 在我的情况下,这没有帮助.什么帮助正在刷新会话...(我仍然不明白为什么需要这样做,因为在事务中看到的其他集合更新.只是这个中间表需要更新的那个没有看到.去图) (2认同)