Erro do tipo Mysql Integrity Constraint Violation na hora de salvar dados no banco

Bom dia Galera,

Estou desenvolvendo uma pequena aplicação desktop através do NetBeans utilizando o Swing, porem estou enfrentando um problema na hora de gravar os dados no banco Mysql. O problema ocorre quando eu clico no botão “salvar” é exibida a seguinte mensagem:

com.mysql.jdbc.exceptions:4,MysqlIntegrityConstraintViolation: Cannot add or update a child row: a foreign key constraint fails ('ControleFinanceiro'.'conta',CONSTRAINT 'subcategoriaId_FK' FOREIGN KEY ('subcategoriaId') REFERENCES 'subcategria' ('id'))

Segue abaixo o código da minha DAO a qual salva no banco de dados:

`

  public void Salvar(Conta c) {
       
       String sql = "insert into conta (tipoconta, pessoaId, categoriaId, subcategoriaId, valor, dataVencimento,   statusConta) VALUES (?,?,?,?,?,?,?)";
                    
        try (PreparedStatement stmt = connection.prepareStatement(sql)){
            stmt.setString(1,c.getTipoConta().getDescricao());
            stmt.setInt(2,c.getPessoaId());
            stmt.setInt(3,c.getCategoriaId());
            stmt.setInt(4,c.getsubCategoriaId());
            stmt.setDouble(5,c.getValor());
            java.sql.Date dtVencimento = java.sql.Date.valueOf(c.getDataVencimento()); 
            stmt.setDate(6,dtVencimento);
            stmt.setString(7, c.getStatusConta().getDescricao());
            stmt.execute();
            stmt.close(); 
            JOptionPane.showMessageDialog(null,"Cadastro de conta realizado com sucesso");
            connection.close();
        }
         catch(SQLException ex) {
            JOptionPane.showMessageDialog(null,"Não foi possível cadastrar a conta no banco de dados\n" + ex);
       }          
}

`

Essas são as minhas tabelas criadas no banco MYSQL Workbench:

`

 CREATE TABLE Categoria
    (id int NOT NULL auto_increment,
    descricao VARCHAR(70) NOT NULL, 
    CONSTRAINT pk_categoriaId primary key(id));


 CREATE TABLE Subcategoria
    (id int NOT NULL auto_increment, 
    tipo VARCHAR(50) NOT NULL,
    CONSTRAINT pk_subcategoriaId primary key(id));


 CREATE TABLE Pessoa
    (id int NOT NULL auto_increment,
    nome VARCHAR(50) NOT NULL,
    nomeBanco VARCHAR(50) NOT NULL,
    saldo decimal(5) NOT NULL,
    CONSTRAINT pk_pessoaId primary key(id));


 CREATE TABLE Conta
    (id smallint(50) NOT NULL auto_increment,
    tipoconta enum ('Pagar','Receber'),
    statusConta enum ('Pendente','Paga','Cancelada'),
    pessoaId INT NOT NULL,
   categoriaId INT NOT NULL,
   subcategoriaId INT NOT NULL,
   valor decimal(5),
   dataVencimento date,
   CONSTRAINT pk_contaId primary key(id),
   CONSTRAINT fk_categoriaId FOREIGN KEY (categoriaId) REFERENCES categoria (id),
   CONSTRAINT fk_subcategoriaId FOREIGN KEY (subcategoriaId) REFERENCES Subcategoria (id),
  CONSTRAINT fk_pessoaId FOREIGN KEY (pessoaId) REFERENCES Pessoa (id));

`

Só para que vocês entendam melhor, o conteúdo das tabelas “Pessoa”, “Categoria” e “Subcategoria” é exibido em um combobox contido no formulário de Cadastro de Conta, sendo assim o usuário deverá selecionar cada campo para cadastrar uma conta, o estranho é que esse erro só ocorre caso eu selecione o primeiro valor vindo de cada uma dessas tabelas, caso eu pegue o valor contido na segunda posição da tabela, o erro não ocorre, isso vale para qualquer uma das 3 tabelas (pessoa, categoria ou subcategoria).

Desde já agradeço os colegas por qualquer ajuda.

A mensagem de erro e bem clara, a fk da sub-categoria que você esta cadastrando para a conta não existe na tabela sub-categoria, debug para verificar qual valor esta tentando gravar, deve ter algum erro na hora de preencher a combo subcategoria.

Oi Bruno, bom dia.

Pelo que entendi, na criação da tabela Conta no banco de dados, você definiu uma restrição de chave estrangeira para SubCategoria, e que no método Salvar(Conta) da sua arquitetura, você define o id da subCategoria da sua Conta.

Muito provavelmente o valor de id da Subcategoria não existe no banco.

Você poderia colocar também o código de exibição do seu ComboBox na sua página e uma lista com as entradas da tabela subcategoria do seu BD?


Edit: Geralmente colocamos o primeiro campo com id 0 para indicar a seleção para o usuário, esse tipo de entrada deve ser validada no seu formulário ou na Servlet/JSF ou outra tecnologia que esteja usando, pois nunca teremos uma ID gerada automaticamente desse valor.

Bom dia Wilsonsf1,

Aqui vai o código contido no meu formulário quando ele é inicializado, o qual é utilizado para preencher os combobox’s referente a “Pessoa”, “Categoria” e “Subcategoria”.

`

    SubCategoriaDao exibirSubcategorias;
    
     try {
      
        exibirSubcategorias = new SubCategoriaDao();
        subcategorias = exibirSubcategorias.RetornaTabela();
      
        if (subcategorias.isEmpty()) {
           JOptionPane.showMessageDialog(null, "Ainda não existe nenhuma subcategoria cadastrada, \n é necessário que se faça o cadastro da mesma primeiro \n para depois lançar uma conta"); 
           this.dispose();
           new FormSubCategoria().show();
        }
      
        for (Subcategoria s : subcategorias)
        {
         cbSubcategoria3.addItem(s);   
        }
    } 
        catch (SQLException ex) {
          Logger.getLogger(Subcategoria.class.getName()).log(Level.SEVERE, null, ex);
        }   

`

E esse seria o metodo contido na minha Dao, o qual traz os dados vindos do meu banco, referente a “subcategoria”.

`

 public List<Conta> RetornaTabela() {
     
    String sql  = "select * from Conta";  
    PreparedStatement stmt;    
    
    try {
    
       stmt = connection.prepareStatement(sql);
       ResultSet rs = stmt.executeQuery();  

       while(rs.next()){  
        
           Conta c = new Conta();
           c.setId(rs.getInt("id"));
           c.setPessoaId(rs.getInt("pessoaId"));
           c.setCategoriaId(rs.getInt("categoriaId"));
           c.setSubCategoriaId(rs.getInt("subcategoriaId"));
           c.setValor(rs.getDouble("valor"));
           c.setDataVencimento(rs.getDate("dataVencimento").toLocalDate());
           c.setSubCategoriaId(rs.getInt("statuscontaId"));
           contas.add(c);
       }   
    } 
    catch (SQLException ex) {
        
        Logger.getLogger(SubCategoriaDao.class.getName()).log(Level.SEVERE, null, ex);
    }
     return contas;  
 }   

`

Sobre a mensagem que você deixou Wilsonsf1, sobre o campo ID 0, acredito que na verdade esse seja o problema, porem devido ao pouco conhecimento, rs, não consegui entender como resolver isso.

Desde já agradeço a ajuda de todos.

E ai galera,

Alguém poderia me dar uma luz…

Desde já agradeço a todos.

Boa tarde Edulemos,

Na verdade o erro só ocorre quando eu escolho o primeiro objeto contido no combobox referente a classe “Pessoa”, “Categoria”, ou “Subcategoria”. Caso eu selecione a segunda opção contida no combobox ele salva normalmente no banco.
Outro detalhe, no meu banco, eu já crio um insert com valores padrão para cada uma dessas tableas, por exemplo, a table Pessoa estou colocando o meu nome e as informações, na table Categoria estou colocando outros dados e na subcategoria também, para que o meu combobox já venha com algumas informações preenchidas por padrão.

Eu precisava saber no caso como começar populando o meu combobox na posição 1, assim como o Wilsonf1 falou… pois assim o erro deixar de ocorrer. Não sei como validar isso no meu formulário.

Desde já agradeço qualquer ajuda.

Valeu galera,

Gostaria de agradecer a ajuda de todos, consegui resolver o meu problema.

Resolveu como? Estou com o mesmo problema!