2012-02-06 100 views
0

我有以下的模型(忽略不相关的/明显的代码,例如getter和setter方法):@OneToMany关系复合键

@Entity 
public class Invoice { 
    @Id // sequence generated 
    private Long invoiceId; 

    @OneToMany(fetch = FetchType.EAGER) 
    @JoinColumn(name = "invoiceId", referencedColumnName = "invoiceId") 
    @OrderBy("id.itemNumber") 
    List<Item> items = new ArrayList<Item>(); 
} 


@Entity 
public class Item { 
    @EmbeddedId 
    private ItemPK id; 
} 


@Embeddable 
public class ItemPK { 
    private Long invoiceId; 
    private Long itemNumber; 
} 

无法更改数据库的结构,因为它是一个传统的DB :(

的itemNumber基本上是从零开始的索引。

如果我利用现有的发票,只是删除现有的项目,在列表中添加2个新项目,试图更新发票对象我遇到的所有时种种问题:

如果我离开ItemPK空,我得到: org.hibernate.TransientObjectException:对象是一个未保存的瞬态的实例 - 合并

之前保存的瞬态的实例。如果我试图填补ItemPK的值我自己(发票和索引的id),我得到:org.hibernate.NonUniqueObjectException:具有相同标识符值的不同对象已与会话相关联(数据库中已经有一个发票项目,并且它具有发票ID和索引= 0,就像我的新项目列表中的第一个对象)。

如果我试图离开invoiceId空(在ItemPK对象),我得到:java.sql.BatchUpdateException:ORA-01400:无法将NULL插入

( “项目”, “invoiceId”。)

有没有办法让Hibernate/JPA来处理呢? 或者我是否需要完全删除关联,将列表定义为@Transient,并将其填充并保存到我的服务类中?

谢谢。

回答

1

这里您实际上有一个双向关联,因为Item实体中的invoiceId实际上是发票的外键。因此,您应该将该关联映射为双向关联,并使用注释。它的javadoc有一个例子。

+0

我有一个类似的问题,并试图使用这个,但无法得到它的工作:http://stackoverflow.com/questions/31600142/how-to-define-onetomany-in-parent-entity-when-儿童具有复合-PK – amphibient 2015-07-24 16:16:41