Hibernate将数据插入连接表中两次,导致Spring Boot项目中"ORA-00001: unique constraint violated"



我有两个用@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 的记录插入两次到我的数据库中pielegniarki_sale JOIN TABLE 中。什么会导致此错误?

因此,Oracle 抛出"ORA-00001:违反唯一约束"。

这是显示双插入的 Spring 引导日志的图片。和实体关系图像

违反唯一约束错误

中东呼吸汇率

您已经两次定义了具有同一实数表的多对多关系。

你必须使其中一个关系成为拥有方,一个关系成为相反的一面。

拥有方是实现中维护间歇性实现表(插入、更新、删除(的一方,另一方,即所谓的反向方,是在插入、更新和删除方面什么都没有发生的一方。

保留侧是在使用指向拥有侧属性的 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 会尝试将两次相同的记录插入到关系表中。

最新更新