Reputation: 41
Using JPA, Hibernate and Postgres, I have an entity with an embedded collection:
@ElementCollection
@CollectionTable(name = "arp_table", joinColumns = @JoinColumn(name = "bsvId"))
private Set<Row> rows;
The embeddable class is like this:
@Embeddable
public class Row
{
@Column(name = "key")
private String key;
@Column(name = "value", nullable = true)
private Integer value;
...
}
and the table is like this:
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
);
(Don't worry, the table & column names aren't really like that.)
Note that the value column is nullable. I've already had problems with hibernate and nulls when trying to use a Map, rather than a Set.
When I update the entity, hibernate tries to delete each row of the collection, then insert rows formed from the collection. But the deletes don't work, because the generated sql is:
delete from arp_table where ... and value = null
which doesn't work, because it should say "value is null". So the inserts fail, with duplicate key violation.
So my question is, can I force hibernate to delete the rows either using the primary key value or simply the id of the parent entity, rather than trying to match on all values? I want to retain the nullability of the value column, because null means something and value can be any int.
Or, of course, am I doing something fundamentally wrong, because this seems like a really simple scenario.
Upvotes: 1
Views: 1939
Reputation: 41
I'll answer my own question. Don't use Set for the collection, use List. Because equals() is not implemented in the Row class (and cannot be, since it doesn't have the id of its containing entity), Set operations do not work correctly. I still don't see why in this case hibernate deletes each row individually, instead of just
delete from arp_table where bsv_id = ?;
but I do now have it working.
Upvotes: 1