Passar statement para preparestatement

24 respostas
M

Oiii gente, a minhas classes dao estão somente com statement e eu gostaria de passa para preparestatement, poderiam me ajudar queridos?

package sql;

import java.sql.Connection;
import java.sql.ResultSet;
import java.sql.SQLException;
import java.sql.Statement;
import java.util.ArrayList;
import java.util.List;

import model.Cliente;

public class AcessoClienteDAO implements ClienteDAO{

	
	public void inserir(Cliente c) throws AcessoClienteException
    {
        Connection conexao = null;
        Statement comando = null;
        try
        {
            conexao = Conexao.getConexao();
            comando = conexao.createStatement();
            String sql = "INSERT INTO cliente VALUES ("+c.getCodc()+",'"+c.getNomec()+"','"+c.getFonec()+"')";
            comando.executeUpdate(sql);
            System.out.println(sql);
            comando.close();
        }
        catch(SQLException e)
        {
            throw new AcessoClienteException("erro de inserção de cliente", e);
        }
        finally
        {
            if(conexao != null)
            {
                try
                {
                    conexao.close();
                }
                catch(SQLException e2)
                {
                }
            }
        }
    }	
	
	public Cliente[] buscarTodos() throws AcessoClienteException
    {
        Connection conexao = null;
        Statement comando = null;
        try
        {
            conexao = Conexao.getConexao();
            comando = conexao.createStatement();
            String sql = "SELECT * FROM cliente";
            ResultSet resultado = comando.executeQuery(sql);
            List<Cliente> lista = new ArrayList<Cliente>();
            while(resultado.next())
            {
                int codc = resultado.getInt("codc");
                String nomec = resultado.getString("nomec");
                String fonec = resultado.getString("fonec");
                lista.add(new Cliente(codc, nomec, fonec));
            }
            resultado.close();
            comando.close();
            return (Cliente[])lista.toArray(new Cliente[0]);
        }
        catch(SQLException e)
        {
        	e.printStackTrace();
            throw new AcessoClienteException("erro de busca de cliente", e);
        	
        }
        finally
        {
            if(conexao != null)
            {
                try
                {
                    conexao.close();
                }
                catch(SQLException e2)
                {
                }
            }
        }
    }
}

beijokas!

24 Respostas

T

Bom dia,

Pra usar PreparedStatement ficaria algo assim:

Connection conexao = null;  
		        PreparedStatement comando = null;  
		        try  
		        {  
  
		            comando = conexao.prepareStatement("INSERT INTO cliente VALUES (?,?,?)");
		            
		            comando.setInt(1, c.getCodc());
		            comando.setString(2, c.getNomec());
		            comando.setString(3, c.getFonec());
		            comando.execute();
		            
		            comando.close();  
		        }  
		        catch(SQLException e)  
		        {  
		            throw new AcessoClienteException("erro de inserção de cliente", e);  
		        }

Note que você deve especificar o indice do atributo a ser setado e pelo tipo!
Faça testes até que tenha o comportamente esperado.

Dê sempre preferência a usar PreparedStatement e nunca concatene os valores na sua query SQL, use sempre a interrogaçãozinha.

Depois pesquise sobre execução em lote com PreparedStatement, o que pode lhe dar um bom ganho de desempenho quando for fazer inserção ou update em lote (com uma massa de dados considerável).

Abraços.

V

Só vai mudar um trechinho:

try { conexao = Conexao.getConexao(); String sql = "INSERT INTO cliente VALUES (?, ?, ?)"; comando = conexao.prepareStatement(sql); comando.setInt(1, c.getCodc()); comando.setString(2, c.getNomec()); comando.setStirng(3, c.getFonec()); comando.executeUpdate(); System.out.println(sql); comando.close(); }

Seria bom mover a linha comando.close() para o bloco finally também.

Note que não é necessário colocar aspas simples no campo que é string. E também não será necessário conhecer o formato da data.

T

Fui 18 segundos mais rápido Vini 8)
hahahaha

D

Bom, vamos lá:

//...
PreparedStatement pState;
//...
String sql = "INSERT INTO cliente VALUES ("+c.getCodc()+",'"+c.getNomec()+"','"+c.getFonec()+"')";   
/*
Ao invés disto
            comando.executeUpdate(sql);   
            System.out.println(sql);
*/
pState = conexao.prepareStatement(sql);
pState.execute();

E

//Ao invés disto
/*
            comando = conexao.createStatement();   
           ResultSet resultado = comando.executeQuery(sql);
*/
conexao = Conexao.getConexao();   
String sql = "SELECT * FROM cliente";   
pState = conexao.prepareStatement(sql);
ResultSet resultado = comando.executeQuery();
T

drsmachado:
Bom, vamos lá:

//...
PreparedStatement pState;
//...
String sql = "INSERT INTO cliente VALUES ("+c.getCodc()+",'"+c.getNomec()+"','"+c.getFonec()+"')";   
/*
Ao invés disto
            comando.executeUpdate(sql);   
            System.out.println(sql);
*/
pState = conexao.prepareStatement(sql);
pState.execute();

E

//Ao invés disto /* comando = conexao.createStatement(); ResultSet resultado = comando.executeQuery(sql); */ conexao = Conexao.getConexao(); String sql = "SELECT * FROM cliente"; pState = conexao.prepareStatement(sql); ResultSet resultado = comando.executeQuery();

Bah, eu não recomendaria fazer desse modo não.
Continua concatenando os valores com a query SQL, então que diferença faz usar PS (PreparedStatement)?

O legal é usar PS pra se reaproveitar a declaração, o banco já fica “experto” com isso e recebe só a diferença da bagaça, sem ter que reinterpretar toda a query novamente.

Por conta disso recomendamos veementemente que se use PS da maneira como o Vini e eu demonstramos acima.

Abraços!

V

Tchello:
Fui 18 segundos mais rápido Vini 8)
hahahaha

O teclado mais rápido do oeste.

T

ViniGodoy:
Tchello:
Fui 18 segundos mais rápido Vini 8)
hahahaha

O teclado mais rápido do oeste.


Tananaaaaaann pananaaaam… (músiquinha do Enio Moricone, num filme do Clint Eastwood ).
Espero que tenham senso de humor e aceitem a brincadeira hehehehe

M

Gente muito obrigada!!
vou tentar aqui e ja falo se deu certinho!
beijokas

V

Ajustei o código ali em cima. Faltou passar o SQL dentro do código do preparedStatement.

M

Obrigada, o inserir então deu certo!
agora fiz o select de acordo com o exemplo acima:

public Cliente[] buscarTodos() throws AcessoClienteException
    {
        Connection conexao = null;
        PreparedStatement comando = null;
        try
        {
        	conexao = Conexao.getConexao();

        	String sql = "SELECT * FROM cliente";     
        	comando = conexao.prepareStatement(sql);  
        	ResultSet resultado = comando.executeQuery();  
        	List<Cliente> lista = new ArrayList<Cliente>();
            while(resultado.next())
            {
                int codc = resultado.getInt("codc");
                String nomec = resultado.getString("nomec");
                String fonec = resultado.getString("fonec");
                lista.add(new Cliente(codc, nomec, fonec));
            }
            resultado.close();
            comando.close();
            return (Cliente[])lista.toArray(new Cliente[0]);
        }
        catch(SQLException e)
        {
        	e.printStackTrace();
            throw new AcessoClienteException("erro de busca de cliente", e);
        	
        }
        finally
        {
            if(conexao != null)
            {
                try
                {
                    conexao.close();
                }
                catch(SQLException e2)
                {
                }
            }
        }
    }

e funcionou, mas mesmo tendo funcionado, ta correto?
Obrigada!

V

Está sim, mas o correto é fechar o statement no finally, assim como você fez com a conexão.

Agora, não era melhor retornar uma List ao invés de retornar um array?

M

certo, então retirei o comando.close() da parte de cima dos dois voids e os coloquei como você falou:

try { conexao.close(); comando.close(); }

Qual seria então a diferença retornando List ?

V

Eu prefiro retornar listas pois são mais fáceis de manipular. É fácil copiar uma lista para um set, ou colocada no interior de um tablemodel.

Seu método nem mudaria muito:

public List&lt;Cliente&gt; buscarTodos() {
   Connection conexao = null;
   PreparedStatement comando = null;
   ResultSet resultado = null;

   try {
      try {
         conexao = Conexao.getConexao();

         String sql = "SELECT * FROM cliente";     
         comando = conexao.prepareStatement(sql);  
         resultado = comando.executeQuery();  

         List&lt;Cliente&gt; lista = new ArrayList&lt;Cliente&gt;();
         while(resultado.next()) {
            int codc = resultado.getInt("codc");
            String nomec = resultado.getString("nomec");
            String fonec = resultado.getString("fonec");
            lista.add(new Cliente(codc, nomec, fonec));
         }
      } finally {
         if (resultado != null) resultado.close();
         if (comando != null) comando.close();
         if (conexao != null) conexao.close();
      }
   } catch(SQLException e) {
      e.printStackTrace();
      throw new AcessoClienteException("erro de busca de cliente", e);        	
   }
}

É uma boa transformar a AcessoClienteException numa RuntimeException. Afinal, há muito poucas chances dela ocorrer, e você já tratou corretamente o fechamento da Conexão, Statement e do ResultSet. Assim o java não exige try…catch na hora de usar o método buscaCliente().

M
Não estou conseguindo acertar as "{}" sempre dá q falta ou tem a mais:
package sql;

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 model.Cliente;

public class AcessoClienteDAO implements ClienteDAO{

	
	public void inserir(Cliente c) throws AcessoClienteException
    {
        Connection conexao = null;
        PreparedStatement comando = null;
        try
        {
        	   conexao = Conexao.getConexao();  
        	   String sql = "INSERT INTO cliente VALUES (?, ?, ?)";
        	   comando = conexao.prepareStatement(sql);  
        	   comando.setInt(1, c.getCodc());
        	   comando.setString(2, c.getNomec());
        	   comando.setString(3, c.getFonec());
        	   comando.executeUpdate();  
        	   System.out.println(sql);  
        	     
        }
        catch(SQLException e)
        {
            throw new AcessoClienteException("erro de inserção de cliente", e);
        }
        finally
        {
            if(conexao != null)
            {
                try
                {
                    conexao.close();
                    comando.close();
                }
                catch(SQLException e2)
                {
                }
            }
        }
    }
	public List<Cliente> buscarTodos() {
		   Connection conexao = null;
		   PreparedStatement comando = null;
		   ResultSet resultado = null;

		   try {
		      try {
		         conexao = Conexao.getConexao();

		         String sql = "SELECT * FROM cliente";     
		         comando = conexao.prepareStatement(sql);  
		         resultado = comando.executeQuery();  

		         List<Cliente> lista = new ArrayList<Cliente>();
		         while(resultado.next()) {
		            int codc = resultado.getInt("codc");
		            String nomec = resultado.getString("nomec");
		            String fonec = resultado.getString("fonec");
		            lista.add(new Cliente(codc, nomec, fonec));
		         }
		      } finally {
		         if (resultado != null) resultado.close();
		         if (comando != null) comando.close();
		         if (conexao != null) conexao.close();
		      } catch(SQLException e) {
		         e.printStackTrace();
		         throw new AcessoClienteException("erro de busca de cliente", e);        	
		      }
		  }
		}

}
agora sobre a classe exception
package sql;

public class AcessoClienteException extends Exception
{
	public AcessoClienteException()
	{
		super();
	}

	public AcessoClienteException(String s)
	{
		super("AcessoClienteException: " + s);
	}

	public AcessoClienteException(String s, Exception e)
	{
		super("AcessoClienteException: " + s, e);
	}
}

eu tenho mais duas classes: produto e pedido, e ambas tem esta classe de exception, se eu mudar para runtime ai seria uma classe então para todas?
Obrigada!

V

Alterei ali as chaves. Tinha mesmo um erro.

A única diferença do RuntimeException é que não necessariamente elas precisam ser capturadas com try...catch. É ideal pra essas exceções que não tem muito tratamento, como a falha do banco de dados.

A classe de exception você muda assim:

package sql;

public class AcessoClienteException extends RuntimeException
{
	public AcessoClienteException()
	{
		super();
	}

	public AcessoClienteException(String s)
	{
		super("AcessoClienteException: " + s);
	}

	public AcessoClienteException(String s, Exception e)
	{
		super("AcessoClienteException: " + s, e);
	}
}

E aí não precisa mais colocar nada no "throws" dos seus métodos.

M

Arrumei ja os exceptions e ja ajeitei o método que tava com o problema do {}
mas agora ele ta reclando para add um statement return ou mudar para void,
se eu arrumar pelo primeiro jeito ele add um "return null" la em baixo, não sei se é o correto, mas pelo menos ele não acusa mais nenhum erro.

} catch(SQLException e) {
		      e.printStackTrace();
		      throw new AcessoClienteException("erro de busca de cliente", e);        	
		   }
		return null;
		}

Muito obrigada pela ajuda até agora, o código ja mudou bastante graças a vocês!

EDIT: da erro: [color=red]sql.AcessoClienteException: AcessoClienteException: erro de inserção de cliente[/color]

EDIT2: essa é a classe de teste
package sql;

import model.Cliente;

public class TesteClienteDAO {

	public static void main(String[] args)
	{
		Cliente c1 = new Cliente(909, "novo", "8888-8888");
		Cliente c2 = new Cliente(905, "nova", "9999-9999");
		ClienteDAO fonte = null;
		try
		{
			fonte = new AcessoClienteDAO();
			fonte.inserir(c1);
			fonte.inserir(c2);
			System.out.println(c2);
			for(Cliente c : fonte.buscarTodos())
            {
                System.out.println(c);
            }	
			
			
		}
		catch(AcessoClienteException e)
		{
			System.out.println(e);
		}
	}



}
V

E qual é o stack trace do erro, que sai impresso no console?

M

oiii,ali em baixo na parte problems mostra:“This method must return a result of type List”

e ali no console mostra:"Exception in thread “main” java.lang.Error: Unresolved compilation problem:
This method must return a result of type List

at sql.AcessoClienteDAO.buscarTodos(AcessoClienteDAO.java:50)
at sql.TesteClienteDAO.main(TesteClienteDAO.java:18)"

Obrigada!

V

Pode postar a versão final do seu método novamente?

M
siiim:
package sql;

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 model.Cliente;

public class AcessoClienteDAO implements ClienteDAO{


	public void inserir(Cliente c) throws AcessoClienteException
	{
		Connection conexao = null;
		PreparedStatement comando = null;
		try
		{
			conexao = Conexao.getConexao();  
			String sql = "INSERT INTO cliente VALUES (?, ?, ?)";
			comando = conexao.prepareStatement(sql);  
			comando.setInt(1, c.getCodc());
			comando.setString(2, c.getNomec());
			comando.setString(3, c.getFonec());
			comando.executeUpdate();  
			System.out.println(sql);  

		}
		catch(SQLException e)
		{
			throw new AcessoClienteException("erro de inserção de cliente", e);
		}
		finally
		{
			if(conexao != null)
			{
				try
				{
					conexao.close();
					comando.close();
				}
				catch(SQLException e2)
				{
				}
			}
		}
	}

	public List<Cliente> buscarTodos() {
		Connection conexao = null;
		PreparedStatement comando = null;
		ResultSet resultado = null;

		try {
			try {
				conexao = Conexao.getConexao();

				String sql = "SELECT * FROM cliente";     
				comando = conexao.prepareStatement(sql);  
				resultado = comando.executeQuery();  

				List<Cliente> lista = new ArrayList<Cliente>();
				while(resultado.next()) {
					int codc = resultado.getInt("codc");
					String nomec = resultado.getString("nomec");
					String fonec = resultado.getString("fonec");
					lista.add(new Cliente(codc, nomec, fonec));
				}
			} finally {
				if (resultado != null) resultado.close();
				if (comando != null) comando.close();
				if (conexao != null) conexao.close();
			}
		} catch(SQLException e) {
			e.printStackTrace();
			throw new AcessoClienteException("erro de busca de cliente", e);        	
		}
	}

}
package sql;

import java.util.List;

import model.Cliente;

public interface ClienteDAO
{
	void inserir(Cliente c) throws AcessoClienteException;
	List<Cliente> buscarTodos() throws AcessoClienteException;

}
V

Faltou mesmo. Só falta fazer

return lista;

Logo abaixo da linha 69.

M

Obrigada querido, funcinou certinho!
beijokas

M
oii gente, não quis abrir outro tópico pq ta relacionado mesmo problema e tema, se eu errei, desculpa! fui arrumar o preparedstatement do inserir pedido mas não deu certo, acho que é por causa das chavez estrangeiras de cliente e videogame
package sql;

import java.sql.Connection;
import java.sql.SQLException;
import java.sql.Statement;

import model.Pedido;
import model.Cliente;
import model.VideoGame;

public class AcessoPedidoDAO implements PedidoDAO{

	public void inserir(Pedido p) throws AcessoPedidoException
    {
        Connection conexao = null;
        Statement comando = null;
        try
        {
            conexao = Conexao.getConexao();
            //String sql = "INSERT INTO pedido VALUES ("+p.getCodp()+",'"+p.getCliente().getCodc()+"','"+p.getVideogame().getCodvg()+")";
            String sql = "INSERT INTO pedido VALUES (?, ?, ?)";
            comando = conexao.prepareStatement(sql);  
			comando.setInt(1, p.getCodp());
			comando.setInt(2, p.getCliente().getCodc());
			comando.setInt(3, p.getVideogame().getCodvg());
			comando.executeUpdate();  
			System.out.println(sql);
        }
        catch(SQLException e)
        {
            throw new AcessoPedidoException("erro de inserção de pedido", e);
        }
        finally
        {
            if(conexao != null)
            {
                try
                {
                    conexao.close();
                }
                catch(SQLException e2)
                {
                }
            }
        }
    }
}

Obrigada!

T

Também gostaria muito de usar preparestatement mas o problema é que faço query’s do género:

rs = query.select("SELECT * FROM car WHERE matricula like '"+matricula+"%'");

E assim dá um erro nos parâmetros do sql como se os parâmetros estivessem errados! :S

ps: não posso fazer o post do código do erro pois tinha que entregar o trabalho na faculdade e voltei ao statament

Criado 13 de novembro de 2010
Ultima resposta 9 de jun. de 2011
Respostas 24
Participantes 5