Hibernate - NonUniqueObjectException

时间:2011-06-03 07:41:44

标签: hibernate jpa jpa-2.0

我在我的应用程序中使用JPA / Hibernate和Spring事务管理。 有一个InspectionEntity与InspectionDetailEntity有一对多的关系。 两个实体的PK都是由数据库中的插入触发器创建的。我尝试保存时的PK值是默认的0值。 我通过调用addInspectionDetail()将InspectionDetailEntity添加到InspectionEntity,然后保存InspectionEntity - entityManager.persist(inspection); 我期望的是检查与所有InspectionDetail一起保存。 但这导致了一个 org.hibernate.NonUniqueObjectException:具有相同标识符值的其他对象已与会话关联:[com.xyz.entity.InspectionDetailEntity#0]。 我还尝试将Set直接设置为InspectionEntity(不使用addInspectionDetail())。这也会导致相同的错误。任何帮助都将受到高度赞赏。

@Entity
@Table(name = "tb_inspection")
public class InspectionEntity {

    @Id
    @Column(name = "inspection_id")
    private Integer inspectionId;

    @OneToMany(fetch = FetchType.EAGER, mappedBy = "inspectionDetailId", cascade = CascadeType.ALL)
    @JoinColumn(name = "inspection_id", insertable = true, updatable = true)
    private Set<InspectionDetailEntity> inspectionDetails;

    /**
     * Adds a inspectionDetailEntity to the set of inspectionDetails
     * @param inspectionDetailEntity
     */
    public void addInspectionDetail(InspectionDetailEntity inspectionDetailEntity) {
        if(inspectionDetails == null)
            inspectionDetails = new HashSet<InspectionDetailEntity>();
        inspectionDetailEntity.setInspection(this);
        inspectionDetails.add(inspectionDetailEntity);
    }
    //setter and getters
}


@Entity
@Table(name = "tb_inspection_dtl")
public class InspectionDetailEntity {

    @Id
    @Column(name = "inspection_dtl_id")
    private Integer inspectionDetailId;

    @Column(name = "inspection_id")
    private Integer inspectionId;

    @ManyToOne
    @JoinColumn(name="inspection_id", insertable = false, updatable = false)
    private InspectionEntity inspection;


    //setters and getters 

}

2 个答案:

答案 0 :(得分:2)

保存前不要将id设置为0。保留为null。如果设置了值,Hibernate将假定该对象已经在数据库中并尝试更新它。

你可能最终得到了具有相同id(0)的多个对象。


更新

正如我想的那样,你可能被迫将id设置为某个值,因为你没有id生成器而Hibernate希望你为id提供值。但是,Hibernate中没有任何内容可以在插入后更新对象上的id。因此,您最终会在会话中使用id为0的多个对象。

我不确定这种情况会有什么好处。您很可能需要编写自定义ID生成器。但是,例如,在序列的情况下,它需要额外调用数据库。可能你应该考虑除了触发器之外的id赋值吗?

答案 1 :(得分:0)

尝试删除

inspectionDetailEntity.setInspection(this);

inspectionDetails.add(inspectionDetailEntity);

我认为你不需要两者。

您的孩子和父母之间的单向关系可能值得考虑