2011-06-01 129 views
1

我有一个表有2个主键(所以他们两个的组合应该是唯一的)。该模式是这样的:多主键表 - 休眠NonUniqueObjectException

TABLE="INVOICE_LOGS" 
INVOICE_NUMBER PK non-null 
INVOICE_TYPE PK non-null 
AMOUNT 

当我尝试一次坚持多条记录,我得到这个休眠例外:

产生的原因: javax.persistence.PersistenceException: org.hibernate作为.NonUniqueObjectException: 具有相同 标识符值不同的物体已经与所述会话相关联 : [... InvoiceLog#110105269]

所以,如果我使用下面的代码,我得到了上面的休眠异常。如果我只保留一条记录,但是如果我试图保留像我正在尝试做的那样的集合,就会失败。

List<InvoiceLog> logs = getLogs(); 
    for(OvercounterLogDO log: logs) { 
     persist(log); 
    } 

    public void persist(final Object entity) { 
     entityManager.persist(entity); 
     entityManager.flush(); 
    } 

Hibernate映射类低于:

@Component(InvoiceLog.BEAN_NAME) 
@Scope(BeanDefinition.SCOPE_PROTOTYPE) 
@Entity 
@Table(name = "INVOICE_LOGS", uniqueConstraints = {@UniqueConstraint(columnNames = "INVOICE_NUMBER"),@UniqueConstraint(columnNames = "INVOICE_TYPE")}) 
public class InvoiceLog implements java.io.Serializable { 

    private static final long serialVersionUID = -7576525197897271909L; 

    protected static final String BEAN_NAME = "invoiceLog"; 

    private long invoiceNumber; 
    private String invoiceType; 
    private Double amount; 

    public InvoiceLog(){} 

    public InvoiceLog(Integer invoiceNumber, String invoiceType, 
      Double amount) { 
     super(); 
     this.invoiceNumber = invoiceNumber; 
     this.invoiceType = invoiceType; 
     this.amount = amount; 
    } 

    @Id 
    @Column(name = "INVOICE_NUMBER", unique = true, nullable = false, precision = 10, scale = 0) 
    public long getInvoiceNumber() { 
     return invoiceNumber; 
    } 
    public void setInvoiceNumber(long invoiceNumber) { 
     this.invoiceNumber = invoiceNumber; 
    } 

// @Id 
    @Column(name = "INVOICE_TYPE", nullable = false, length = 4) 
    public String getInvoiceType() { 
     return invoiceType; 
    } 
    public void setInvoiceType(String invoiceType) { 
     this.invoiceType = invoiceType; 
    } 

    @Column(name = "AMOUNT", nullable = false, length = 12) 
    public Double getAmount() { 
     return amount; 
    } 
    public void setAmount(Double amount) { 
     this.amount = amount; 
    } 

} 

回答

3

您当前的映射具有一个单一的标识,invoiceNumber,而不是化合物键。因此,它会要求invoiceNumber是唯一的,而不是你想要的组合。这是例外情况告诉你的,它注意到你正试图用相同的Id值保存第二条记录。

您需要将两个字段映射为组合键。它看起来从你的第二个@Id注释出你在某个时间点朝着那个方向。 Here's the documentation关于映射组合键的方法。