Home > Enterprise >  Referential integrity constraint violation when trying to delete
Referential integrity constraint violation when trying to delete

Time:01-26

I'm trying to create an API for saving a Person and its Address, like in this model:

Text

fk_id_pessoa is supposed to be a foreing key to associate many addresses to one person

fk_main_address is for assign a main address to a person.

And i'm getting this error when trying to delete a Person that has a foreing key in the address table:

2023-01-24T19:58:27.952-03:00  WARN 15492 --- [nio-8080-exec-4] o.h.engine.jdbc.spi.SqlExceptionHelper   : SQL Error: 23503, SQLState: 23503
2023-01-24T19:58:27.952-03:00 ERROR 15492 --- [nio-8080-exec-4] o.h.engine.jdbc.spi.SqlExceptionHelper   : Referential integrity constraint violation: "FK4Y8KCQU7650VDPKHN1C54N3TB: PUBLIC.ENDERECO FOREIGN KEY(ID) REFERENCES PUBLIC.PESSOA(ID) (1)"; SQL statement:
delete from pessoa where id=? [23503-214]

Models:

Person

package com.apitest.api.model;

import java.util.Date;

import jakarta.persistence.CascadeType;
import jakarta.persistence.Column;
import jakarta.persistence.Entity;
import jakarta.persistence.GeneratedValue;
import jakarta.persistence.GenerationType;
import jakarta.persistence.Id;
import jakarta.persistence.JoinColumn;
import jakarta.persistence.OneToOne;
import jakarta.persistence.Table;

@Entity
@Table(name = "pessoa")
public class Pessoa {


    @Id
    @GeneratedValue(strategy = GenerationType.AUTO)
    private Integer id;


    @Column(name = "nome")
    private String nome;

    @Column(name = "dataNascimento")
    private Date dataNascimento;


    @OneToOne(cascade = CascadeType.ALL)
    @JoinColumn(name = "id_endereco")
    private Endereco endereco;

    public Pessoa(Integer id, String nome, Date dataNascimento, Endereco endereco) {
        this.id = id;
        this.nome = nome;
        this.dataNascimento = dataNascimento;
        this.endereco = endereco;
    }


    public Pessoa(){

    };


    public Integer getId() {
        return this.id;
    }

    public void setId(Integer id) {
        this.id = id;
    }

    public String getNome() {
        return nome;
    }

    public void setNome(String nome) {
        this.nome = nome;
    }

    public Date getDataNascimento() {
        return dataNascimento;
    }

    public void setDataNascimento(Date dataNascimento) {
        this.dataNascimento = dataNascimento;
    }


    public Endereco getEndereco() {
        return endereco;
    }


    public void setEndereco(Endereco endereco) {
        this.endereco = endereco;
    }




    

    
}

Address


package com.apitest.api.model;

import jakarta.persistence.CascadeType;
import jakarta.persistence.Column;
import jakarta.persistence.Entity;
import jakarta.persistence.GeneratedValue;
import jakarta.persistence.GenerationType;
import jakarta.persistence.Id;
import jakarta.persistence.JoinColumn;
import jakarta.persistence.ManyToOne;
import jakarta.persistence.Table;

@Entity
@Table(name = "endereco")
public class Endereco {

    @Id
    @GeneratedValue(strategy = GenerationType.AUTO)
    private Integer id_endereco;

    @Column(name = "logradouro")
    private String logradouro;

    @Column(name = "cep")
    private String cep;

    @Column(name = "numero")
    private String numero;


    @Column(name = "cidade")
    private String cidade;

    @ManyToOne(cascade = CascadeType.ALL)
    @JoinColumn(name = "id")
    private Pessoa pessoa;

    

    public Endereco(Integer id_endereco, String logradouro, String cep, String numero, String cidade, Pessoa pessoa) {
        this.id_endereco = id_endereco;
        this.logradouro = logradouro;
        this.cep = cep;
        this.numero = numero;
        this.cidade = cidade;
        this.pessoa = pessoa;
    }

    public Endereco(){

    };


    public String getLogradouro() {
        return logradouro;
    }


    public void setLogradouro(String logradouro) {
        this.logradouro = logradouro;
    }


    public String getCep() {
        return cep;
    }


    public void setCep(String cep) {
        this.cep = cep;
    }


    public String getNumero() {
        return numero;
    }


    public void setNumero(String numero) {
        this.numero = numero;
    }


    public String getCidade() {
        return cidade;
    }


    public void setCidade(String cidade) {
        this.cidade = cidade;
    }


    public Pessoa getPessoa() {
        return pessoa;
    }


    public void setPessoa(Pessoa pessoa) {
        this.pessoa = pessoa;
    }


    public Integer getId_endereco() {
        return id_endereco;
    }


    public void setId_endereco(Integer id_endereco) {
        this.id_endereco = id_endereco;
    }

    
}


Controllers:

Person

package com.apitest.api.controller;

import java.util.List;

import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.http.HttpStatus;
import org.springframework.http.ResponseEntity;
import org.springframework.web.bind.annotation.DeleteMapping;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.PathVariable;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.PutMapping;
import org.springframework.web.bind.annotation.RequestBody;
import org.springframework.web.bind.annotation.RestController;

import com.apitest.api.model.Pessoa;

import com.apitest.api.service.PessoaService;

@RestController
public class PessoaController {

    @Autowired
    private PessoaService pessoaService;

    @GetMapping("/pessoas")
    public ResponseEntity<List<Pessoa>> getAllPessoa(){
        return ResponseEntity.ok().body(pessoaService.getAllPessoa());
    }

    @PostMapping("/pessoas")
    public ResponseEntity<Pessoa> createPessoa(@RequestBody Pessoa pessoa){

        return ResponseEntity.ok().body(this.pessoaService.createPessoa(pessoa));

    }
    
    @GetMapping("/pessoas/{id}")
    public ResponseEntity<Pessoa> getPessoaById(@PathVariable Integer id){
        return ResponseEntity.ok().body(pessoaService.getPessoaById(id));
    }


    @PutMapping("/pessoas/{id}")
    public ResponseEntity<Pessoa> updatePessoa(@PathVariable Integer id, @RequestBody Pessoa pessoa){
        pessoa.setId(id);
        return ResponseEntity.ok().body(this.pessoaService.updatePessoa(pessoa));
    }

    @DeleteMapping("/pessoas/{id}")
    public HttpStatus deletePessoa (@PathVariable Integer id){
        this.pessoaService.deletePessoa(id);

        return HttpStatus.OK;

    }

    @PostMapping("/pessoas/{id}/{fkIdEndereco}")
    public ResponseEntity<Pessoa> setEnderecoPrincipal(@PathVariable Integer id, @PathVariable Integer fkIdEndereco){
        
        return ResponseEntity.ok().body(this.pessoaService.setEnderecoPrinicpal(id, fkIdEndereco));
    }

    
}

Address:

package com.apitest.api.controller;

import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.http.ResponseEntity;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.RequestBody;
import org.springframework.web.bind.annotation.RestController;

import com.apitest.api.model.Endereco;
import com.apitest.api.service.EnderecoService;

@RestController
public class EnderecoController {

    @Autowired
    private EnderecoService enderecoService;


    @PostMapping("/endereco")
    public ResponseEntity<Endereco> createEndereco(@RequestBody Endereco endereco){

        return ResponseEntity.ok().body(this.enderecoService.createEndereco(endereco));

    }


    
}


Service:

Person

package com.apitest.api.service;

import java.util.List;
import java.util.Optional;

import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import com.apitest.api.model.Endereco;
import com.apitest.api.model.Pessoa;
import com.apitest.api.repository.EnderecoRepository;
import com.apitest.api.repository.PessoaRepository;

@Service
@Transactional
public class PessoaServiceImpl implements PessoaService {

    @Autowired
    private PessoaRepository pessoaRepository;

    @Autowired
    private EnderecoRepository enderecoRepository;

    @Override
    public Pessoa createPessoa(Pessoa pessoa) {

        return pessoaRepository.save(pessoa);

    }

    @Override
    public Pessoa updatePessoa(Pessoa pessoa) {
        Optional<Pessoa> pessoaDb = this.pessoaRepository.findById(pessoa.getId());
        
        Pessoa pessoaUpdate = pessoaDb.get();
        pessoaUpdate.setId(pessoa.getId());
        pessoaUpdate.setNome(pessoa.getNome());
        pessoaUpdate.getNome();

        if(pessoa.getEndereco() != null){
            Optional<Endereco> enderecoDb = this.enderecoRepository.findById(pessoa.getEndereco().getId_endereco());
            pessoaUpdate.setEndereco(pessoa.getEndereco());
        }

    
        return pessoaUpdate;
    }

    @Override
    public Pessoa getPessoaById(Integer idPessoa) {
        Optional<Pessoa> pessoaDb = this.pessoaRepository.findById(idPessoa);
        if(pessoaDb.isPresent()){
            return pessoaDb.get();
        }

        return null;
    }

    @Override
    public List<Pessoa> getAllPessoa() {
        return this.pessoaRepository.findAll();
    }

    @Override
    public void deletePessoa(Integer idPessoa) {
        Optional<Pessoa> pessoaDb = this.pessoaRepository.findById(idPessoa);
        
        if(pessoaDb.isPresent()){
            this.pessoaRepository.delete(pessoaDb.get());
        }
    }

    @Override
    public Pessoa setEnderecoPrinicpal(Integer idPessoa, Integer idEndereco) {
        // TODO Auto-generated method stub
        return null;
    }

    /*@Override
    public Pessoa setEnderecoPrinicpal(Integer idPessoa, Integer idEndereco) {

        Optional<Pessoa> pessoaDb = this.pessoaRepository.findById(idPessoa);
        Optional<Endereco> enderecoDb = this.enderecoRepository.findById(idEndereco);

        Pessoa pessoa = pessoaDb.get();
        Endereco endereco = enderecoDb.get();

        if(endereco.getPessoa() != null && (pessoa.getId() == endereco.getPessoa().getId())){
            pessoa.setFkIdEnderecoPrincipal(endereco);
            return pessoa;
        }
        else{
            return null;
        }

    }*/
    
}


Address

package com.apitest.api.service;

import java.util.Optional;

import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;

import com.apitest.api.model.Endereco;
import com.apitest.api.model.Pessoa;
import com.apitest.api.repository.EnderecoRepository;
import com.apitest.api.repository.PessoaRepository;

import org.springframework.transaction.annotation.Transactional;

@Service
@Transactional
public class EnderecoServiceImpl implements EnderecoService {

    @Autowired
    private EnderecoRepository enderecoRepository;
    
    @Autowired
    private PessoaRepository  pessoaRepository;


    @Override
    public Endereco createEndereco(Endereco endereco) {

        if(endereco.getPessoa() != null){
            Optional<Pessoa> pessoaDb = this.pessoaRepository.findById(endereco.getPessoa().getId());
            Pessoa pessoaUpdate = pessoaDb.get();
            endereco.setPessoa(pessoaUpdate);
        }

        return enderecoRepository.save(endereco);

    }
    
}


I have put "cascade = CascadeType.ALL" in both fields but didnt helped. I also think that "fk_main_address" is mapped wrong. Any help would be appreciated.

CodePudding user response:

It is the database that is complaining. You need to update the Person table, setting the main address FK to Nil. Then you will be able to delete the record.

CodePudding user response:

I identified that the @JoinColumn annotation of the pessoa field in Endereco is wrong, the @JoinColumn should be the foreign key referring to the field, so it would be fk_id_pessoa and not id, follow the example link

  • Related