休眠持续@Embeddable对象的集合抛出异常

问题描述:

我的类看起来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的主键。并且您尝试使用相同的主键插入两行。如果它不应该存在,则放弃主键约束。 –

使用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