Error when storing data from a Select with Java

1

Good morning. I would like to know if you have the possibility of storing in a variable the value of a search ( select ). In case I want to store a id of another table with the use of select , however after doing .executeQuery() , it does not send me that id .

String nomeCliente = (String) cbNomeCliente.getSelectedItem(); // receber o que está escrito no combobox
String nomeFuncionario = (String) cbNomeFuncionario.getSelectedItem();
String nomeLivro = (String) cbNomeLivro.getSelectedItem();

String sql, sqlChamaChaveCliente, sqlChamaChaveFuncionario, sqlChamaChaveLivro;
ResultSet recebeCli, recebeFunc, recebeLivro; 

try{
   //Class.forName("com.mysql.jdbc.Driver");
   conexao = DriverManager.getConnection(url, usuario, senha);
   stm = conexao.createStatement();

   sqlChamaChaveCliente = (String) "select idcliente from cliente where nome='" + nomeCliente +"'";
   sqlChamaChaveFuncionario = (String) "select idfuncionario from funcionario where nome ='" + nomeFuncionario+"'";
   sqlChamaChaveLivro = (String) "select idLivro from livro where nome_liv ='" + nomeLivro +"'";

   recebeCli   =   stm.executeQuery(sqlChamaChaveCliente);
   recebeFunc  =   stm.executeQuery(sqlChamaChaveFuncionario);
   recebeLivro =   stm.executeQuery(sqlChamaChaveLivro);

In these variables " recebeCli ", " recebeFunc " and " recebeLivro " I want to save the value of the query.

Note: I'm new to java.

    
asked by anonymous 25.11.2017 / 14:48

2 answers

4

First, there is no reason to save letters in variable names, which is a bad programming practice.

Second, use the try-with-resources .

Third, avoid SQL Injection using PreparedStatement .

Fourth, you'd prefer to use DAO standard to do this type of thing.

Assuming that the fields in your cliente table are id , nome , telefone and cpf , your code looks something like this:

import java.sql.Connection;
import java.sql.PreparedStatement;
import java.sql.ResultSet;
import java.sql.SQLException;
import java.util.ArrayList;
import java.util.List;
import java.util.Optional;

public class ClienteDAO {
    private static String POR_NOME =
            "SELECT id, nome, telefone, cpf FROM cliente WHERE nome = ?";

    private static String POR_ID =
            "SELECT id, nome, telefone, cpf FROM cliente WHERE id = ?";

    private final Connection conexao;

    public ClienteDAO(Connection conexao) {
        this.conexao = conexao;
    }

    private Cliente popular(ResultSet rs) throws SQLException {
        int id = rs.getInt(1);
        String nome = rs.getString(2);
        String telefone = rs.getString(3);
        String cpf = rs.getString(4);
        return Cliente.criar(id, nome, telefone, cpf);
    }

    private List<Cliente> listar(PreparedStatement statment) throws SQLException {
        try (ResultSet rs = statement.executeQuery()) {
            List<Cliente> resultado = new ArrayList<>();
            while (rs.next()) {
                Cliente c = popular(rs);
                resultado.add(c);
            }
            return resultado;
        }
    }

    private Optional<Cliente> ler(PreparedStatement statment) throws SQLException {
        try (ResultSet rs = statement.executeQuery()) {
            if (rs.next()) return Optional.of(popular(rs));
            return Optional.empty();
        }
    }

    public List<Cliente> porNome(String nome) throws SQLException {
        try (PreparedStatement statement = conexao.prepareStatement(POR_NOME)) {
            statement.setString(1, nome);
            return listar(statement);
        }
    }

    public Optional<Cliente> porId(int id) throws SQLException {
        try (PreparedStatement statement = conexao.prepareStatement(POR_ID)) {
            statement.setInt(1, id);
            return ler(statement);
        }
    }
}

Other methods that bring results from the cliente table are added to this same class. You will do something similar for the other classes. Public methods will correspond to each type of query that your DAO is able to do, and will use private methods ler(PrepaparedStatement) and listar(PreparedStatement) to form the results.

Note that the results can be List<Cliente> for the case where there may be several (or no) results. For the case where there can only be one or no result, you use Optional<Cliente> .

It is also necessary to have a criar method in the Cliente class that creates an instance containing all the necessary data. I'll tell you more about this on that other answer of mine .

Next, you'll join DAOs more or less like this:

import java.sql.DriverManager;
import java.sql.SQLException;

public class ParametrosDeConexao {

    private final String url;
    private final String usuario;
    private final String senha;

    public ParametrosDeConexao(String url, String usuario, String senha) {
        this.url = url;
        this.usuario = usuario;
        this.senha = senha;
    }

    public Connection conectar() throws SQLException {
        return DriverManager.getConnection(url, usuario, senha);
    }
}
import java.sql.Connection;
import java.sql.SQLException;

public class CamadaDeDados implements AutoCloseable {
    private final Connection conexao;
    private final ClienteDAO clientes;
    private final FuncionarioDAO funcionarios;
    private final LivroDAO livros;

    public CamadaDeDados(ParametrosDeConexao params) throws SQLException {
        this.conexao = params.conectar();
        this.clientes = new ClienteDAO(conexao);
        this.funcionarios = new FuncionarioDAO(conexao);
        this.livros = new LivroDAO(conexao);
    }

    public ClienteDAO clientes() {
        return clientes;
    }

    public FuncionarioDAO funcionarios() {
        return funcionarios;
    }

    public LivroDAO livros() {
        return livros;
    }

    @Override
    public void close() throws SQLException {
        conexao.close();
    }
}

Now that we have the data access layer organized, you can do this:

private ParametrosDeConexao params() {
    return new ParametrosDeConexao(url, usuario, senha);
} 

private void seuMetodo() {
    String nomeCliente = (String) cbNomeCliente.getSelectedItem();
    String nomeFuncionario = (String) cbNomeFuncionario.getSelectedItem();
    String nomeLivro = (String) cbNomeLivro.getSelectedItem();

    int idCliente, idFuncionario, idLivro;
    try (CamadaDeDados c = new CamadaDeDados(params())) {
        idCliente = c.clientes().porNome(nomeCliente).get(0).getId();
        idFuncionario = c.funcionarios().porNome(nomeFuncionario).get(0).getId();
        idLivro = c.livros().porNome(nomeLivro).get(0).getId();
    } catch (SQLException x) {
        JOPtionPane.showMessageDialog(null, x.getMessage());
    }
}

Ideally, you should use the MVC design pattern so that presentation logic (which deals with JComboBox s and JOptionPane s) is not stuck with your modeling logic (which implements rules and concepts of books, employees and customers). However, I would need more information about your project to show you how to do this, and then it would be the case to ask another question, as this is well beyond the purpose of this one.

These get(0) I had to put are probably not ideal, being unwanted things. However, to get rid of them, I would need to have more information about your project. With these get(0) what I did was simply assume that there will always be one and only one result, but this is a dangerous thing to assume because the listing methods by name can bring more than one result or may bring none, which means that we might not find the% s of searched% s or find more than id , and if that happens, then you'll have to see what you're going to do.

In well-designed professional projects using JDBC, you'll never or almost never just search for the id in the database. You will almost always want to get the entire tuple. That's why DAO methods return id and List<Cliente> instead of just Optional<Cliente> . So I also suspect that your approach to searching for int is not correct.

Note that if id , url , and usuario are fixed and immutable, you can set senha to a variable ParametrosDeConexao and always reuse the same instance.

Each time you use an object of type private static final within try-with-resources , you are performing a database operation on a single connection. It is also the ideal place to implement transaction control when / if you need it.

    
26.11.2017 / 00:15
1

The response from @VictorStafusa is very good and very complete, but being a bit more direct ... You can use ResultSet :

try{
   //Class.forName("com.mysql.jdbc.Driver");
   conexao = DriverManager.getConnection(url, usuario, senha);
   stm = conexao.createStatement();

   sqlChamaChaveCliente = "select idcliente from cliente where nome='" + nomeCliente +"'";

   ResultSet rsCliente = stm.executeQuery(sqlChamaChaveCliente);
   while(rsCliente.next()) {
        idcliente = rsCliente.getInt("idcliente");
   }
}

Now, as mentioned in the other answer, there are some points of attention:

  • You need to ensure that all features are closed: the Connection, the Statement, and the ResultSet. You can close them "on hand" or use try-with-resources if you are using Java 7 +

  • The code in this way is fully capable of SQL Injection . Instead of using Statement , use PreparedStatement .

28.11.2017 / 11:44