问题
Let's say I have following model structure:
@Entity
@Table(....)
public class AnnotationGroup{
...
private List<AnnotationOption> options;
@OneToMany(cascade = CascadeType.ALL, fetch = FetchType.EAGER, orphanRemoval = true)
@JoinColumn(name = "annotation_group_id", nullable = false)
public List<AnnotationOption> getOptions() {
return options;
}
}
@Entity
@Table(...)
public class AnnotationOption {
private Long id;
@Id
@GeneratedValue(strategy = GenerationType.IDENTITY)
@Override
public Long getId() {
return id;
}
}
At the moment I have group1
with AnnotationOption
s opt1
opt2
and opt3
Then I want to replace all option with only one option opt1
Additionally I have constraint in database:
CONSTRAINT "UQ_ANNOTATION_OPTION_name_annotation_group_id" UNIQUE (annotation_option_name, annotation_group_id)
And this one fires:
Caused by: org.postgresql.util.PSQLException: ERROR: duplicate key value violates unique constraint "UQ_ANNOTATION_OPTION_name_annotation_group_id"
Detail: Key (name, annotation_group_id)=(opt1, 3) already exists.
Actually isuue that hibernate removes orphans after update.
Can you suggest something t resolve issue?
回答1:
There are so many things that are wrong in this example:
- EAGER fetching on the
@OneToMany
collection is almost always a bad idea. - Unidirectional collections are also bad, use the bidirectional one.
- If you get this exception, most likely you cleared all the elements and re-added back the ones that you want to be retained.
The best way to fix it is to explicitly merge the existing set of children with the incoming ones so that:
- New child entities are being added to the collection.
- The child entities that are no longer needed are removed.
- The child entities matching the business key (
annotation_group_name
,study_id
) are updated with the incoming data.
For more details, check out High-Performance Java Persistence.
回答2:
According to Hibernate documentation hibernate perform in the following order to preserve foreign-key constraint:
- Inserts, in the order they were performed
- Updates
- Deletion of collection elements
- Insertion of collection elements
- Deletes, in the order they were performed
For your special need you should manually flush the transaction to force the deletion in database before.
来源:https://stackoverflow.com/questions/46214322/how-to-force-hibernate-to-remove-orphans-before-update