代码之家  ›  专栏  ›  技术社区  ›  PaiS

JPA manytomy产生的空联接表

  •  6
  • PaiS  · 技术社区  · 16 年前

    我有一个应用程序,在其中我尝试使用Hibernate作为我的JPA提供者来实现两个实体之间的许多关系。

    我正在尝试的例子是一个单向的,其中一个相机可以有多个镜头,镜头可以放入多个相机。

    下面是我的实体类…(只是粘贴它的相关部分)

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

    在测试用例中,我尝试像这样保存相机实例。。。

    @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\u LENS)。只在每个镜头和相机表中创建一行,因此不能满足许多人的需要。然而,DDL是为连接表生成的,它也会被创建,只是它没有任何记录。

    如有任何帮助或指点,将不胜感激。

    1 回复  |  直到 16 年前
        1
  •  5
  •   PaiS    16 年前

    我发现了问题。有点奇怪。我使用的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 (?)
    

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

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

    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个表中。

    希望这能帮助别人更进一步。。。