我有两个使用 @ManyToMany 注释映射的实体
第一
皮耶格尼亚卡:
@Data
@Entity
@Table(name = "pielegniarka")
public class Pielegniarka {
@Id
@SequenceGenerator(name = "seq2", sequenceName = "pielegniarka_id_pielegniarki", allocationSize = 1)
@GeneratedValue(strategy = GenerationType.SEQUENCE, generator = "seq2")
@Column(name = "id_pielegniarki", nullable = false, unique = true)
private int id_pielegniarki;
@Column(name = "imie")
private String imie;
@Column(name = "nazwisko")
private String nazwisko;
@Column(name = "placa")
private int placa;
@ManyToMany(fetch = FetchType.LAZY, cascade = {CascadeType.DETACH,CascadeType.MERGE,
CascadeType.PERSIST,CascadeType.REFRESH})
@JoinTable(
name = "pielegniarki_sale",
joinColumns = @JoinColumn(name = "id_pielegniarki"),
inverseJoinColumns = @JoinColumn(name = "nr_sali")
)
private List<Sala> sale;
public Pielegniarka() {
}
public Pielegniarka(String imie, String nazwisko, int placa, List<Sala> sale) {
this.imie = imie;
this.nazwisko = nazwisko;
this.placa = placa;
this.sale = sale;
}
public void addSala(Sala sala){
if(sale == null){
sale = new ArrayList<>();
}
sale.add(sala);
}
public void removeSala(Sala sala){
sale.remove(sala);
sala.getPielegniarki().remove(this);
}
}
第二
萨拉:
@Data
@Entity
@Table
public class Sala {
@Id
@SequenceGenerator(name = "seq3", sequenceName = "sala_nr_sali_seq", allocationSize = 1)
@GeneratedValue(strategy = GenerationType.SEQUENCE, generator = "seq3")
@Column(name = "nr_sali", nullable = false, unique = true)
private int nr_sali;
@Column(name = "pojemnosc")
private int pojemnosc;
@Column(name = "oddzial")
private String oddzial;
@JsonBackReference
@ManyToMany(fetch = FetchType.LAZY, cascade = {CascadeType.DETACH,CascadeType.MERGE,
CascadeType.PERSIST,CascadeType.REFRESH})
@JoinTable(
name = "pielegniarki_sale",
joinColumns = @JoinColumn(name = "nr_sali"),
inverseJoinColumns = @JoinColumn(name = "id_pielegniarki")
)
private List<Pielegniarka> pielegniarki;
public Sala() {
}
public Sala(int pojemnosc, String oddzial, List<Pielegniarka> pielegniarki) {
this.pojemnosc = pojemnosc;
this.oddzial = oddzial;
this.pielegniarki = pielegniarki;
}
public void addPielegniarka(Pielegniarka pielegniarka){
if(pielegniarki == null){
pielegniarki = new ArrayList<>();
}
pielegniarki.add(pielegniarka);
}
public void removePielegniarka(Pielegniarka pielegniarka){
pielegniarki.remove(pielegniarka);
pielegniarka.getSale().remove(this);
}
}
我的 SalaDAO 中还有一个方法(以及 PielegniarkaDAO 中的类似方法),它将 Pielegniarka 添加到 Sala 类中的列表,然后将该 Sala 的 id 和新添加的 Pielegniarko 的 id 插入到我的 Oracle 数据库中的联接表中(因为 @ ManyToMany注释)
@Override
public void saveSalaWithIdPielegniarki(int idPielegniarki, int nr_sali) {
Pielegniarka pielegniarka = entityManager.find(Pielegniarka.class, idPielegniarki);
Sala sala = entityManager.find(Sala.class, nr_sali);
if (pielegniarka != null && sala != null) {
for (Pielegniarka salPiel : sala.getPielegniarki()) {
if (salPiel.getId_pielegniarki() == idPielegniarki) {
return;
}
}
pielegniarka.addSala(sala);
sala.addPielegniarka(pielegniarka);
}
}
这是 SalaController 的一个片段,显示了执行此操作的方法。在服务类中我使用了与 DAO 中完全相同的方法。它只是 DAO 类的包装器。
@RestController
@RequestMapping("/sala")
public class SalaController {
@PostMapping("/{nr_sali}/pielegniarka/{idPielegniarki}")
public void saveSalaWithIdPielegniarki(@PathVariable int idPielegniarki,
@PathVariable int nr_sali) {
salaService.saveSalaWithIdPielegniarki(idPielegniarki,nr_sali);
}
}
当我尝试访问此端点时,例如/sala/4/pielegniarka/5 ,它应该将 id 为 5 的 Pielegniarka 添加到 id 为 4 的 sala 列表中,Hibernate 会将 id 为 4,5 的记录插入到ielegniarki_sale JOIN TABLE中两次我的数据库。什么可能导致此错误?
Oracle 因此抛出“ORA-00001:违反唯一约束”。
这是显示双插入的 Spring Boot 日志的图片。与实体关系图片
最佳答案
您使用同一个关系表两次定义了 ManyToMany 关系。
您必须将其中一个关系设为拥有关系,将一个关系设为相反关系。
拥有方是关系中维护中间关系表的一方(插入、更新、删除),另一方,即所谓的反向方,是在插入、更新方面没有发生任何事情的一方并删除。
当您使用指向拥有方属性的mappedBy属性时,定义了受控方。
例如,您可以拥有这样的所有权方:
@ManyToMany(fetch = FetchType.LAZY, cascade = {CascadeType.DETACH,CascadeType.MERGE,
CascadeType.PERSIST,CascadeType.REFRESH})
@JoinTable(
name = "pielegniarki_sale",
joinColumns = @JoinColumn(name = "nr_sali"),
inverseJoinColumns = @JoinColumn(name = "id_pielegniarki")
)
private List<Pielegniarka> pielegniarki;
然后反面是这样的:
@ManyToMany(fetch = FetchType.LAZY, cascade = {CascadeType.DETACH,CascadeType.MERGE,
CascadeType.PERSIST,CascadeType.REFRESH}, mappedBy = "pielegniarki")
private List<Pielegniarka> pielegniarki;
如果您不这样做并让它像您的映射一样,那么 Hibernate 会尝试将同一记录插入到关系表中两次。
关于java - Hibernate两次向Join Table插入数据导致Spring Boot项目出现 "ORA-00001: unique constraint violated",我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/59546543/