休眠将数据两次插入到联接表中,从而导致"ORA-00001:违反了唯一约束".在Spring Boot项目中 [英] Hibernate inserts data into Join Table twice causing "ORA-00001: unique constraint violated" in Spring Boot project

查看:131
本文介绍了休眠将数据两次插入到联接表中,从而导致"ORA-00001:违反了唯一约束".在Spring Boot项目中的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我有两个使用@ManyToMany注释映射的实体

I've got two entities mapped with @ManyToMany annotation

第一

Pielegniarka:

Pielegniarka:


 @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数据库的Join Table中(由于@ ManyToMany注释)

I also have a method in my SalaDAO (and similar method in PielegniarkaDAO) which adds Pielegniarka to list in Sala class and then inserts id of that Sala and id of newly added Pielegniarko to Join Table in my Oracle Database (because of @ManyToMany annotation)

  @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类的包装.

Here is a fragment of SalaController which shows the method doing this. In-service classes I used exactly the same methods as in DAO. It is only a wrapper for DAO classes.

@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中我的数据库.什么会导致此错误?

When I try to access this endpoint for example /sala/4/pielegniarka/5 which should add Pielegniarka with id 5 to the list of sala with id 4, Hibernate inserts record with id's 4,5 twice into pielegniarki_sale JOIN TABLE in my Database. What can cause this error?

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

Oracle is throwing "ORA-00001: unique constraint violated" because of that.

这是显示两次插入的Spring Boot日志的图片.与实体的关系图

Here is the picture of Spring Boot logs that show double insert. And entities relationships image

违反了唯一约束错误

MER

推荐答案

您已经两次使用相同的表定义了ManyToMany关系.

You have two times defined a ManyToMany relationship with the same realtion table.

您必须使关系之一成为拥有关系,而使关系相反.

You have to make one of the relations the owning and one the inverse side.

拥有一方是房地产中维护中间房地产表(插入,更新,删除)的那一侧,而另一面,即所谓的反面,是在插入,更新方面什么都没有发生的那一侧并删除.

The owning side is the side in the realtionship from where the intermidate realtion table is maintainted (insert, update, delete) and the other side, the so called inverse side, is the side where nothing happens in terms of insert, update and delete.

当您使用指向拥有方属性的mappedBy属性时,将定义保留方.

The inserves side is defined when you use the mappedBy attribute that points to the owning side attribute.

例如,您可能拥有这样的拥有权:

For example you could have the owning side like this:

@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会尝试将两次相同的记录插入到关系表中.

If you don't do this and let it like your mapping then Hibernate tries to insert two time the same record to the relation table.

这篇关于休眠将数据两次插入到联接表中,从而导致"ORA-00001:违反了唯一约束".在Spring Boot项目中的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
相关文章
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆