2017-09-22 118 views
0

我有以下实体:唯一约束违反有关休眠更新到一对多集合

@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; 
    } 
} 

现在我需要更新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 

运行,我得到以下异常:

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] 

我预计所有'老'(='孤立')Service s将被删除,当我拨打setServices与新的HashSet。我做错了什么? TIA!

回答

2

尝试明确列表以前设置服务:

license.getServices().clear(); 

然后

license.getServices.add("firstService"); 
licenseRepository.save(license); 

UPDATE

为了使这项工作,这是很重要实施equalshashCode方法。我正在使用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(); 
} 
+0

前加入这样的事情,我已经这样做,在'License.setServices'。 – t777

+0

是不一样清除之前单独添加 查找此http://docs.jboss.org/hibernate/orm/5.2/userguide/html_single/Hibernate_User_Guide.html#collections-值 –

+0

好吧。我试过了,但是我得到了同样的错误。 – t777

4

只要在集合上调用.clear()可能不够。可能它需要明确调用remove(),然后清除它的每个组件。

请尝试清除设置,看看是否能解决问题

this.services.forEach(service -> {licenseRepository.remove(service)}); 
+0

谢谢。但我不能这样做。我需要一些级联解决方案。 – t777