我有一个应用程序,其中我尝试使用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>();
...
}
镜头:
@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;
...
}
在测试用例中,我尝试像这样坚持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);
}
持久性成功发生,并且Hibernate没有抛出错误/异常。但是,与期望相反,JoinTable中不会创建行(在本例中为CAMERA_LENS)。仅在每个镜头和相机表中创建一行,因此不符合ManyToMany的目的。但是,为连接表生成DDL并创建它,但只是它没有任何记录。
非常感谢任何帮助或指示。
答案 0 :(得分: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个表中,但是一旦给出了传播策略,一切都证明是好的。
另一个有趣的观察是我尝试将传播策略作为MANDATORY放在方法级别(以检查是否存在导致第一个和错误情况的事务),但是该方法引发了一个异常,表明不存在任何事务,仍然将数据保存到2个表中。
希望能帮助某人继续......