持久化多对多列时发生jpa主键冲突

时间:2012-04-25 01:55:56

标签: java jpa eclipselink

我的实体是: deiveID设备的ID 与...有多对多的关系 Lib的ID是rID

我的测试代码是: 两个新设备实体想要设置相同的新自由度

问题是: 如果我使用相同的实体管理器来保存这2个新设备实体,那就没问题了。 但如果我使用2个不同的entitymanager实例来持久化它们,则会出现错误“主键违规”。我认为实体经理试图在第二次坚持自由,这已经是第一次持续存在。

-------------- deviceinfo entity ------------------------------- -----------------

@Entity
@Table(name="deviceInfo")
public class DeviceInfoEntity extends BaseEntity implements Serializable{

@Id
@GeneratedValue(strategy = GenerationType.AUTO)
private long deviceId;
....
@ManyToMany(cascade=CascadeType.ALL,fetch=FetchType.LAZY)
@JoinTable(name = "device_lib", joinColumns = @JoinColumn(name = "deviceInfo_id",
  referencedColumnName="deviceId"), 
  inverseJoinColumns = @JoinColumn(name = "lib_id", referencedColumnName="rId"))
private List<LibEntity> resourceList = null;
......
}

------------------------- lib entity -------------------- -------------------------

    @Entity
    @Table(name="lib")
    public class LibEntity extends BaseEntity implements Serializable{
           @Id
       @GeneratedValue(strategy = GenerationType.AUTO)
       private long rId;

          @ManyToMany(mappedBy = "resourceList", cascade=CascadeType.ALL,
                  fetch=FetchType.LAZY, targetEntity=DeviceInfoEntity.class)
       private List<DeviceInfoEntity> deviceInfolist = null;

           .....
    }

我的测试代码是:

EntityManagerFactory emFactory = Persistence.createEntityManagerFactory("testPU");
          EntityManager em = emFactory.createEntityManager();


    LibEntity libEntity = new LibEntity();


    DeviceInfoEntity dEntity = new DeviceInfoEntity();
    dEntity.setName("dadadada");
    dEntity.setLibEntity(libEntity);


    DeviceInfoEntity dEntity2 = new DeviceInfoEntity();
    dEntity2.setName("dadadadadddddd");
    dEntity2.setLibEntity(libEntity);


    em.getTransaction().begin();
    em.persist(dEntity);
    em.getTransaction().commit();

    em.close();

    EntityManager em2 = emFactory.createEntityManager();
    em2.getTransaction().begin();
    em2.persist(dEntity2);
    em2.getTransaction().commit();

它会出错:

 Unique index or primary key violation: "PRIMARY KEY ON PUBLIC.LIB(RID)"; SQL statement:
 INSERT INTO lib (RID) VALUES (?) [23505-165]

但如果我使用相同的EntityManager,则不会发生错误。有没有人知道什么原因?是由cascade=CascadeType.ALL

引起的

1 个答案:

答案 0 :(得分:3)

通过将已分离的对象分配给托管对象,您正在破坏持久性上下文。托管对象应该只引用其他托管对象。

对于dEntity2,您应该将libEntity设置为libEntity的find(),getReference()或merge()的结果。

dEntity2.setLibEntity(em2.find(libEntity.getClass(), libEntity.getId());

您也可以调用merge()而不是persist(),它应该解析分离的对象。