2016-05-02 40 views
0

我的類看起來simiar這樣:(要約類)休眠持續@Embeddable對象的集合拋出異常

@Entity 
public class Offer { 
    @Id 
    @GeneratedValue(strategy = GenerationType.TABLE) 
    private int id; 
    @ElementCollection(fetch = FetchType.LAZY) 
    private Set<Product> products; 

    ...other fields 
} 

及產品類:

@Embeddable 
public class Product { 
    private String name; 
    private String description; 
    private int amount; 
} 

問題是,當我試圖堅持的提供實體並嘗試向提供套件添加兩個對象:

Product product = new Product("ham", "description1", 1); 
Product product = new Product("cheese", "description2", 1); 

我收到異常:

Caused by: org.postgresql.util.PSQLException: ERROR: duplicate key value violates unique constraint "offer_products_pkey" 
    Details: Key (offer_id, amount)=(1, 1) already exists. 

我不知道爲什麼我不能堅持兩個可嵌入的對象在設置時,其中一個具有相同的「金額」字段值?它以某種方式作爲ID處理?

也許我不應該創建可嵌入對象的列表,因爲它不是像這樣使用的?如果是這樣 - 那麼如果我不需要一個產品實體但想要將它保存在另一個實體(供應)中呢?

預先感謝幫助

+1

您可能在表產品中定義了錯誤的鍵。異常很明顯 – mariusz2108

+0

我沒有產品對象中的任何關鍵變量。如果我使用列表而不是設置它工作正常,但對於設置它不。問題似乎與Set界面的功能密切相關 - 它不能包含重複項。但爲什麼字段「金額」被視爲重複? – azalut

+0

錯誤來自PostgreSQL。它會告訴您什麼是錯誤的:您已經爲(offer_id,amount)定義了名爲offer_products_pkey的主鍵。並且您嘗試使用相同的主鍵插入兩行。如果它不應該存在,則放棄主鍵約束。 –

回答

0

使用Set時的問題是,內容必須是唯一的,因爲這是一個Set的定義。 JPA提供程序將嘗試使用數據庫約束來強制執行此操作。在你的例子中,它以Primary Key,Offer_id和int Amount的形式添加一個約束,儘管恕我直言,它應該爲Product屬性的所有值添加一個約束。看到這一點的最好辦法是使SQL日誌,看看到底是怎麼回事在幕後:

Hibernate: create table Offer (id integer not null, primary key (id)) 
Hibernate: create table Offer_products (Offer_id integer not null, amount integer not null, description varchar(255), name varchar(255), primary key (Offer_id, amount)) 
Hibernate: alter table Offer_products add constraint FKmveai2l6gf4n38tuhcddby3tv foreign key (Offer_id) references Offer 

解決這個問題的辦法是使Offer一個List代替Setproducts屬性:

Hibernate: create table Offer (id integer not null, primary key (id)) 
Hibernate: create table Offer_products (Offer_id integer not null, amount integer not null, description varchar(255), name varchar(255)) 
Hibernate: alter table Offer_products add constraint FKmveai2l6gf4n38tuhcddby3tv foreign key (Offer_id) references Offer