使用JPA,Hibernate和Postgres,我有一个带有嵌入式集合的实体:
@ElementCollection
@CollectionTable(name = "arp_table", joinColumns = @JoinColumn(name = "bsvId"))
private Set<Row> rows;
嵌入式类是这样的:
@Embeddable
public class Row
{
@Column(name = "key")
private String key;
@Column(name = "value", nullable = true)
private Integer value;
...
}
,桌子就是这样:
CREATE TABLE arp_table
(
bsv_id bigint NOT NULL,
key character varying(255) NOT NULL,
value int,
CONSTRAINT pk_arp_bsv_id_request_priority PRIMARY KEY (bsv_id, key),
CONSTRAINT fk_arp_bsv_id FOREIGN KEY (bsv_id)
REFERENCES bsv_table (id) MATCH SIMPLE
ON UPDATE NO ACTION ON DELETE NO ACTION
);
(不用担心,表格名称并非如此。)
请注意,值列是无效的。尝试使用地图而不是集合时,我已经遇到了冬眠和无效的问题。
当我更新实体时,Hibernate试图删除集合的每一行,然后插入从集合中形成的行。但是删除不起作用,因为生成的SQL是:
delete from arp_table where ... and value = null
不起作用,因为它应该说"价值为null"。因此,插入物失败了,重复的键违反。
所以我的问题是,我可以强迫Hibernate使用主密钥值或简单地使用父实体的ID删除行,而不是尝试匹配所有值?我想保留值列的无效性,因为null表示某些内容和价值可以是任何int。
当然,我在从根本上做错了什么,因为这似乎是一个非常简单的场景。
我会回答自己的问题。不要将设置用于集合,请使用列表。由于Equals()未在行类中实现(并且由于它没有其包含实体的ID),因此设置操作无法正常工作。我仍然不明白为什么在这种情况下,Hibernate会单独删除每一行,而不仅仅是
delete from arp_table where bsv_id = ?;
,但我现在确实有效。