[英]Unique constraint violation on hibernate update to OneToMany collection
I have the following entities: 我有以下实体:
@Entity
public class License {
// ...
@OneToMany(mappedBy = "license", cascade = CascadeType.ALL, fetch = FetchType.EAGER, orphanRemoval = true)
private Set<Service> services = new HashSet<>();
// ...
protected void setServices(Set<String> services) {
this.services.clear();
if (services != null) {
this.services.addAll(services.stream().map(s -> new Service(this, s)).collect(toSet()));
}
}
}
@Entity
@Table(uniqueConstraints = @UniqueConstraint(name = "UQ_lic_service", columnNames = { "license_id", "service" }))
public class Service {
// ...
@ManyToOne(cascade = CascadeType.ALL)
@JoinColumn(name = "license_id", nullable = false)
private License license;
@Column(nullable = false, length = 255)
private String service;
protected Service(License license, String service) {
this.license = license;
this.service = service;
}
}
Now I need to update the License
like: 现在,我需要像以下那样更新
License
:
License license = getSomeExistingLicenseWithServices(...);
// The existing license has two services "firstService", "secondService"
HashSet<String> services = new HashSet<>();
services.add("firstService");
license.setServices(services);
licenseRepository.save(license); // A spring-data-jpa-repository
Running this, I get the following exception: 运行此命令,我得到以下异常:
Caused by: org.h2.jdbc.JdbcSQLException: Eindeutiger Index oder Primärschlüssel verletzt: "UQ_LIC_SERVICE_INDEX_8 ON PUBLIC.SERVICE(LICENSE_ID, SERVICE) VALUES (1, 'firstService', 1)"
Unique index or primary key violation: "UQ_LIC_SERVICE_INDEX_8 ON PUBLIC.SERVICE(LICENSE_ID, SERVICE) VALUES (1, 'firstService', 1)"; SQL statement:
insert into service (id, lock_no, license_id, service) values (null, ?, ?, ?) [23505-196]
I expected all 'old' (='orphaned') Service
s to become deleted, when I call setServices
with a new HashSet
. 当我使用新的
HashSet
调用setServices
时,我希望所有“旧”(=“孤立”) Service
将被删除。 What I am doing wrong? 我做错了什么? TIA!
TIA!
Just calling .clear() on the set may not be enough. 仅在集合上调用.clear()可能还不够。 Likely its requiring an explicit call to remove() on each component of the set before clearing it.
可能需要在清除集之前对集合的每个组件进行显式调用remove()。
please try adding something like this before clearing the set to see if that solves the issue 请先尝试添加类似的内容,然后再清除该集合以查看是否可以解决问题
this.services.forEach(service -> {licenseRepository.remove(service)});
Try to clear the list before setting the services: 尝试在设置服务之前 清除列表:
license.getServices().clear();
And then 接着
license.getServices.add("firstService");
licenseRepository.save(license);
UPDATE 更新
To make this work, it is important to implement the equals
and hashCode
methods. 为了使这项工作有效,实现
equals
和hashCode
方法很重要。 I'm using apache commons lang library 我正在使用apache commons lang库
@Override
public int hashCode() {
return new HashCodeBuilder().append(idService).toHashCode();
}
@Override
public boolean equals(Object obj) {
if (!(obj instanceof Service))
return false;
Service other = (Service) obj;
return new EqualsBuilder()
.append(this.idService, other.idService)
.isEquals();
}
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.