Error in CRUD command UPDATE - java.sql.SQLException: No value specified for parameter 8

2

I'm building a Java system with MySQL database connection, but I stopped at some point because I can not find the error. My update method happens an error in JUnit, but I can not figure out what it is.

Follows parts of the code:

package com.sistemacliente.DAO;

import java.sql.Connection;
import java.sql.Date;
import java.sql.PreparedStatement;
import java.sql.ResultSet;
import java.sql.SQLException;
import java.util.ArrayList;

import com.sistemacliente.domain.Balada;
import com.sistemacliente.domain.Cliente;
import com.sistemacliente.factory.ConexaoFactory;

public class ClienteDAO {


    public void salvar(Cliente c) throws SQLException {
        StringBuilder sql = new StringBuilder();
        sql.append("INSERT INTO cliente");
        sql.append("(nome,sobrenome,telefone,email,data,valor,baladas_codigo)");
        sql.append("VALUES (?,?,?,?,?,?,?)");

        Connection conexao = ConexaoFactory.conectar();

        PreparedStatement comando = conexao.prepareStatement(sql.toString());
        comando.setString(1, c.getNome());
        comando.setString(2, c.getSobrenome());
        comando.setInt(3, c.getTelefone());
        comando.setString(4, c.getEmail());
        comando.setDate(5, c.getData());
        comando.setDouble(6, c.getValor());
        comando.setInt(7, c.getBalada().getCodigo());

        comando.executeUpdate();

    }

    public ArrayList<Cliente> listar() throws SQLException {

        StringBuilder sql = new StringBuilder();
        sql.append(
                "SELECT c.codigo, c.nome, c.sobrenome, c.telefone, c.email, c.data, c.valor, b.codigo, b.descricao ");
        sql.append("FROM cliente c   ");
        sql.append("INNER JOIN balada b ON b.codigo = c.baladas_codigo");

        Connection conexao = ConexaoFactory.conectar();

        PreparedStatement comando = conexao.prepareStatement(sql.toString());

        ResultSet resultado = comando.executeQuery();

        ArrayList<Cliente> lista = new ArrayList<Cliente>();

        while (resultado.next()) {
            Balada b = new Balada();
            b.setCodigo(resultado.getInt("b.codigo"));
            b.setDescricao(resultado.getString("b.descricao"));

            Cliente c = new Cliente();
            c.setCodigo(resultado.getInt("c.codigo"));
            c.setNome(resultado.getString("c.nome"));
            c.setSobrenome(resultado.getString("c.sobrenome"));
            c.setTelefone(resultado.getInt("c.telefone"));
            c.setEmail(resultado.getString("c.email"));
            c.setData(resultado.getDate("c.data"));
            c.setValor(resultado.getDouble("c.valor"));
            c.setBalada(b);

            lista.add(c);
        }
        return lista;

    }

    public void excluir(Cliente c) throws SQLException {
        StringBuilder sql = new StringBuilder();
        sql.append("DELETE FROM cliente ");
        sql.append("WHERE codigo = ?");

        Connection conexao = ConexaoFactory.conectar();

        PreparedStatement comando = conexao.prepareStatement(sql.toString());
        comando.setInt(1, c.getCodigo());
        comando.executeUpdate();

    } 

    public void atualizar(Cliente c) throws SQLException {

        StringBuilder sql = new StringBuilder();
        sql.append("UPDATE cliente");
        sql.append("SET codigo = ? , nome = ? , sobrenome = ? , telefone = ? ,"
                + " email = ? ,  data = ? , valor = ? , baladas_codigo = ? ");
        sql.append("WHERE codigo =  ? ");

        Connection conexao = ConexaoFactory.conectar();

        PreparedStatement comando = conexao.prepareStatement(sql.toString());

        comando.setString(1, c.getNome());
        comando.setString(2, c.getSobrenome());
        comando.setInt(3, c.getTelefone());
        comando.setString(4, c.getEmail());
        comando.setDate(5, c.getData());
        comando.setDouble(6, c.getValor());
        comando.setInt(7, c.getCodigo());

        comando.executeUpdate();

    } 
}

And here is the part of JUnit:

    @Test
    public void atualizar() throws SQLException {

        Cliente c = new Cliente();
        c.setCodigo(7);
        c.setNome("Koppa");
        c.setSobrenome("Troppa");
        c.setTelefone(11111);
        c.setEmail("[email protected]");
        c.setData(new Date(2016/07/10));
        c.setValor(5.00);

        Balada b = new Balada();
        b.setCodigo(14);
        c.setBalada(b);

        ClienteDAO dao = new ClienteDAO();
        dao.atualizar(c);

    }
}

Here is the error generated:

  

java.sql.SQLException: No value specified for parameter 8

Error Screenshot:

    
asked by anonymous 17.12.2016 / 20:36

2 answers

2
  • There is no way to use StringBuilder to construct a String each time each method is called, and always the same String will be built. Using a fixed% prefix already prefabricated is much better and simpler.

  • Note that if any exceptions are thrown, String , ResultSet and / or PreparedStatement are not closed anywhere, and therefore are kept open, which can cause several problems. Even if you explicitly call Connection methods, you should take care to ensure that they are called even if the execution is aborted with an exception (and hence the close() usage must be remembered). However, it is for this type of situation that the try-with-resources syntax is designed in Java 7.

  • Setting the type to finally is not considered good programming practice when ArrayList<AlgumaCoisa> is sufficient. The main reason is that using List<AlgumaCoisa> (except in the constructor) means that you are coding for an implementation, whereas with ArrayList<AlgumaCoisa> you are coding for an interface. Good practices in object-oriented software development say that it is best to code for an interface rather than an implementation.

  • Use the diamond syntax that Java 7 introduced to avoid having to repeat generic types in builders.

  • This code here:

    StringBuilder sql = new StringBuilder();
    sql.append("UPDATE cliente");
    sql.append("SET codigo = ? , nome = ? , sobrenome = ? , telefone = ? ,"
            + " email = ? ,  data = ? , valor = ? , baladas_codigo = ? ");
    sql.append("WHERE codigo =  ? ");
    

    Produces the following List<AlgumaCoisa> :

    UPDATE clienteSET codigo = ? , nome = ? , sobrenome = ? , telefone = ? , email = ? ,  data = ? , valor = ? , baladas_codigo = ? WHERE codigo =  ? 
    

    This String has two problems. The first problem is that by using String , you did not mind the spaces and ended up producing StringBuilder all together, which obviously gives a sinatxe error in SQL.

    The second problem is that it does not make sense for you to put the client code twice, since the client code entered in clienteSET (the client to be changed) is the same as WHERE . You're not trying to change the client code here, and it only makes sense to put in SET what you want to change. So the first SET should not be there.

  • Your update code does not define all the fields that should be defined. It failed to fill in the field of the ballad code and also lacked the first code of the client (but according to item 5 above, this should not be in SQL itself).

    Here's how your code looks with these problems all sorted out:

    package com.sistemacliente.DAO;
    
    import java.sql.Connection;
    import java.sql.Date;
    import java.sql.PreparedStatement;
    import java.sql.ResultSet;
    import java.sql.SQLException;
    import java.util.ArrayList;
    
    import com.sistemacliente.domain.Balada;
    import com.sistemacliente.domain.Cliente;
    import com.sistemacliente.factory.ConexaoFactory;
    
    public class ClienteDAO {
    
        private static final String SQL_SALVAR = "INSERT INTO cliente (nome, sobrenome, telefone, email, data, valor, baladas_codigo) VALUES (?, ?, ?, ?, ?, ?, ?)";
    
        public void salvar(Cliente c) throws SQLException {   
            try (
                Connection conexao = ConexaoFactory.conectar();
                PreparedStatement comando = conexao.prepareStatement(SQL_SALVAR);
            ) {
                comando.setString(1, c.getNome());
                comando.setString(2, c.getSobrenome());
                comando.setInt(3, c.getTelefone());
                comando.setString(4, c.getEmail());
                comando.setDate(5, c.getData());
                comando.setDouble(6, c.getValor());
                comando.setInt(7, c.getBalada().getCodigo());
                comando.executeUpdate();
            }
        }
    
        private static final String SQL_LISTAR = "SELECT c.codigo, c.nome, c.sobrenome, c.telefone, c.email, c.data, c.valor, b.codigo, b.descricao FROM cliente c INNER JOIN balada b ON b.codigo = c.baladas_codigo";
    
        public List<Cliente> listar() throws SQLException {
            List<Cliente> lista = new ArrayList<>();
    
            try (
                Connection conexao = ConexaoFactory.conectar();
                PreparedStatement comando = conexao.prepareStatement(SQL_LISTAR);
                ResultSet resultado = comando.executeQuery();
            ) {
                while (resultado.next()) {
                    Balada b = new Balada();
                    b.setCodigo(resultado.getInt("b.codigo"));
                    b.setDescricao(resultado.getString("b.descricao"));
    
                    Cliente c = new Cliente();
                    c.setCodigo(resultado.getInt("c.codigo"));
                    c.setNome(resultado.getString("c.nome"));
                    c.setSobrenome(resultado.getString("c.sobrenome"));
                    c.setTelefone(resultado.getInt("c.telefone"));
                    c.setEmail(resultado.getString("c.email"));
                    c.setData(resultado.getDate("c.data"));
                    c.setValor(resultado.getDouble("c.valor"));
                    c.setBalada(b);
    
                    lista.add(c);
                }
            }
            return lista;
        }
    
        private static final String SQL_EXCLUIR = "DELETE FROM cliente WHERE codigo = ?";
    
        public void excluir(Cliente c) throws SQLException {
            try (
                Connection conexao = ConexaoFactory.conectar();
                PreparedStatement comando = conexao.prepareStatement(SQL_EXCLUIR);
            ) {
                comando.setInt(1, c.getCodigo());
                comando.executeUpdate();
            }
        }
    
        private static final String SQL_ATUALIZAR = "UPDATE cliente SET nome = ?, sobrenome = ?, telefone = ?, email = ?, data = ?, valor = ?, baladas_codigo = ? WHERE codigo = ?";
    
        public void atualizar(Cliente c) throws SQLException {
            try (
                Connection conexao = ConexaoFactory.conectar();
                PreparedStatement comando = conexao.prepareStatement(SQL_ATUALIZAR);
            ) {
                comando.setString(1, c.getNome());
                comando.setString(2, c.getSobrenome());
                comando.setInt(3, c.getTelefone());
                comando.setString(4, c.getEmail());
                comando.setDate(5, c.getData());
                comando.setDouble(6, c.getValor());
                comando.setInt(7, c.getBalada().getCodigo());
                comando.setInt(8, c.getCodigo());
                comando.executeUpdate();
            }
        } 
    }
    
        
  • 18.12.2016 / 04:37
    1

    Well, I have not programmed in Java for some time, but I believe your error is here:

        StringBuilder sql = new StringBuilder();
        sql.append("UPDATE cliente");
        sql.append("SET codigo = ? , nome = ? , sobrenome = ? , telefone = ? ,"
                + " email = ? ,  data = ? , valor = ? , baladas_codigo = ? ");
        sql.append("WHERE codigo =  ? ");
    

    First point, it is not recommended to update the code when it is the primary key and especially when it is in the WHERE condition. And notice that you spent 9 times the ? , so it will wait for you to pass 9 values later in the case you did not. You have put only 7, missing baladas_codigo :

        comando.setString(1, c.getNome());
        comando.setString(2, c.getSobrenome());
        comando.setInt(3, c.getTelefone());
        comando.setString(4, c.getEmail());
        comando.setDate(5, c.getData());
        comando.setDouble(6, c.getValor());
        comando.setInt(7, c.getCodigo());
    

    The correct one would be something close to that:

     public void atualizar(Cliente c) throws SQLException {
    
        StringBuilder sql = new StringBuilder();
        sql.append("UPDATE cliente");
        sql.append("SET nome = ? , sobrenome = ? , telefone = ? ,"
                + " email = ? ,  data = ? , valor = ? , baladas_codigo = ? ");
        sql.append("WHERE codigo =  ? ");
    
        Connection conexao = ConexaoFactory.conectar();
    
        PreparedStatement comando = conexao.prepareStatement(sql.toString());
    
        comando.setString(1, c.getNome());
        comando.setString(2, c.getSobrenome());
        comando.setInt(3, c.getTelefone());
        comando.setString(4, c.getEmail());
        comando.setDate(5, c.getData());
        comando.setDouble(6, c.getValor());
        comando.setDouble(7, c.getBaladas_codigo());// Aqui é só um exemplo, poi pelo que vi, esta em outra tabela, ou você retira do SQL ou passa de alguma forma
    
        comando.setInt(8, c.getCodigo());
    
        comando.executeUpdate();
    
    } 
    

    I believe it is the error that is happening. Anything comments here, if I could not explain it well!

        
    17.12.2016 / 23:11