[Resolvido] java.sql.SQLException: Illegal operation on empty result set

Boa Tarde gurizada! Seguinte, tou com um problema aqui, esse insert tá me retornando empty result set, já googlei de monte e não acho o que pode ser. eu quero que esse insert, além dos campos de texto, envie a data como um numero (pex: 01/06/2010 => 01062010 pro DB, pra depois eu retomar esse numero (01062010) e jogar na máscara. os inserts de texto tão funcionando tranquilo, começou a dar esse erro depois de eu inserir a data tbm =S

vai ali a criança:


import java.awt.*;
import java.awt.event.*;
import java.io.*;
import java.sql.*;
import java.text.*;


import javax.lang.model.util.Types;
import javax.swing.*;
import javax.swing.table.TableCellRenderer;
import javax.swing.table.TableColumn;
import javax.swing.text.MaskFormatter;
import javax.swing.text.AttributeSet.ColorAttribute;


/**
 * @author Mauricio
 * 
 */
public class CadFun extends JFrame {

	JLabel jlb_codigo, jlb_nome, jlb_nascimento, jlb_carteira, jbl_rg, jbl_cpf,
			jlb_endereco, jlb_bairro, jlb_municipio, jlb_estado, jlb_telefone,
			jlb_celular, jlb_email, jlb_funcao, jlb_obs, jlb_admissao, jlb_demissao,
			jlb_horarios;
	JTextField jtf_codigo, jtf_nome, jtf_nascimento, jtf_carteira, jtf_rg,
			jtf_cpf, jtf_endereco, jtf_bairro, jtf_telefone, jtf_celular,
			jtf_email, jtf_funcao, jtf_admissao;
	JFormattedTextField jft_nascimento, jft_admissao, jft_demissao;
	JTextArea jta_obs;
	JComboBox jcb_municipio, jcb_estado, jcb_horarios;
	JButton jbt_primeiro, jbt_anterior, jbt_proximo, jbt_ultimo, jbt_gravar,
			jbt_alterar, jbt_deletar, jbt_consultar, jbt_horarios, jbt_sair;
	MaskFormatter data;
	
	String codigo, nome, nascimento, carttrab, rg, cpf, endereco, bairro, telefone, celular, email, funcao, obs, admissão;
	String estado, municipio, horarios;
	String admi, demi, nasc;
	int id;
	public CadFun() {
//--**--**--**--**--**--**--**--**--**--**--**--**--**--**--**--**--**--**--**--**--**--**--**--**--**--**--**
		//remover mascaras
		admi = jft_admissao.getText();
		demi = jft_demissao.getText();
		nasc = jft_nascimento.getText();
		if (admi.contains("/")) 
		{
		if (admi.contains("/")) 
		admi = admi.replace("/", ""); 
		}
		if (demi.contains("/")) 
		{if (demi.contains("/")) 
		demi = demi.replace("/", ""); 
		}
		
		if (demi.contains("/")) 
		{if (nasc.contains("/")) 
		nasc = nasc.replace("/", ""); 
		}
//--------------------------------------------------------------------------------------------------------------
		jbt_gravar.addActionListener(new ActionListener()
		{
			public void actionPerformed(ActionEvent evento)
			{
				inserir();
			}
		});
	}// Final Construtor
	private void inserir/*termiado*/() 
	{
		try {
			int id;
			ResultSet rs; 
			Connection con;
			con 			= gConexao.getConexao();
			Statement st 	= con.createStatement();
			
			rs = st.executeQuery("Select max(IDFUNCIONARIO) as id from funcionarios");
			rs.next();
			
			id = rs.getInt("id")+1;
			rs = st.executeQuery
			("SELECT idmunicipio from `municipios` where descricao = '"+jcb_municipio.getSelectedItem()+"' " +
					"and idestado = "+jcb_estado.getSelectedIndex());
			rs.next();
			
			int municipio = rs.getInt("idmunicipio");
			String end = jtf_endereco.getText();
			end.toString();
			String obs = jta_obs.getText(); obs.toString();
			
			st.executeUpdate("INSERT INTO `funcionarios`" +
					"(idfuncionario, nome, nascimento," +
					" cart_trabalho, rg, cpf,endereco," +
					" fone, cell, email," +
					" funcao, admissao, demissao, obs," +
					" id_estado, id_municipio, horario) " +
					"VALUES" +
					"("+id+", '"+jtf_nome.getText()+"', '"+nasc+"', '"
					+jtf_carteira.getText()+"', '"+jtf_rg.getText()+"', '"+jtf_cpf.getText()+"', '"+end+"', '"
					+jtf_telefone.getText()+"', '"+jtf_celular.getText()+"', '"+jtf_email.getText()+"', '"
					+jtf_funcao.getText()+"', '"+admi+"', '"+demi+"', '"+obs+"', "+
					jcb_estado.getSelectedIndex()+", "+municipio+", "+jcb_horarios.getSelectedIndex()+")");
			
			jtf_codigo.setText(Integer.toString(id));
			JOptionPane.showMessageDialog(null,"Registro Inserido Com Sucesso!!!","Gerenciamento de estados."
					,JOptionPane.INFORMATION_MESSAGE);
		} 
		catch (Exception e) {
			System.out.println(e);
			JOptionPane.showMessageDialog(null,"Erro: "+e,"Gerenciamento de estados."
					,JOptionPane.INFORMATION_MESSAGE);
		}
	   
	}

}// Final CadFun

Em vez de

            rs.next();  

você tem de usar

if (rs.next()) {
    // Processar, do jeito que você já fez
    ...
} else {
    // neste caso não há registros, talvez mostrar uma mensagem dizendo que não achou.
    ...
}

hmmm…

não entendi direito.eu uso um if pra cada rs.next()?

e então, se cada if for verdadeiro, eu passo pra próxima query, isso?

pq ali eu to chamando um método de inserção, então eu espero q não tenha nenhum registro. e que pegue os dados da aplicação e crie um… :pensativo:

Quem espera sempre “cança” - você não ouviu falar nisso?

De qualquer maneira, cheque se seu select não está errado. O valor de rs.next() deve sempre ser checado, porque pode ser que a consulta não retorne nenhum registro.

Outra coisa, recomendo fortemente que você substitua esse monte de concatenação aí pelo uso do PreparedStatement. Não é mais difícil de fazer, ele já trata automaticamente campos String digitados com caracteres como apóstrofe (’), deixa a aplicação independente do formato de data do banco e também deixa o código muito mais limpo.

Sem falar que elimina completamente a chance de alguém fazer um ataque de SQL Injection.

Ok, vou fazer isso. tou reescrevendo do zero essa parte de código. se duvida vai se mais rápido que descobri como faze aquela coisa funciona.

xD

Cara, é pra fica mais ou menos assim o código do preparedstatment? pq tá dando uns errinhos na setagem dos campos…

é que eu nunca fiz prepared, achei um fonte de exemplo no google e me larguei modifica… é isso mesmo??

[code] PreparedStatement stmt;
rs = st.executeQuery(“SELECT max(idfuncionario) as id FROM funcionarios”);
if(rs.next())
idfun = rs.getInt(“id”);

        String query = "insert into funcionarios " +
        "(IDFuncionario,nome,nascimento,cart_trabalho,rg,cpf,endereco,bairro,id_estado,id_municipio,fone,cell,email,funcao,horario,admissao,demissao,obs) VALUE"+
        "(idfu = ?, pnome = ?, pnasc = ?, pcart = ?, prg = ?, pcpf = ?, pendereco = ?)";
        stmt = con.prepareStatement(query);  
        stmt.setLong(idfun, idfu);  
        stmt.setString(2, pnome);  
        stmt.setString(3, pnasc); [/code]

dá pra ve q eu ñ terminei ele ainda, é que deu esses erros e eu mandei pra cá, pra depois ñ ter de reescreve tudo caso eu teja fazendo errado… :?

Bom, o código tá dando pau (novidade…)

onde eu errei? ele inseriu o registro numero 0 no banco, mas não insere depois disso… retorna chave duplicada…

aqui o erro>

com.mysql.jdbc.exceptions.jdbc4.MySQLIntegrityConstraintViolationException: Duplicate entry '0' for key 1

aqui o código>

[code]private void inserir()
{

	try {
		ResultSet rs;
		Connection con;
		con = gConexao.getConexao();
        Statement st = con.createStatement();
        
        rs = st.executeQuery("SELECT max(idfuncionario) as id FROM funcionarios");
        if(rs.next()) {
        idfun = rs.getInt("id")+1;
        
        	rs = st.executeQuery("SELECT idmunicipio from `municipios` where descricao = '"+jcb_municipio.getSelectedItem()+"' and Idestado = "+jcb_estado.getSelectedIndex());
        	if(rs.next())
        		idmun = rs.getInt("idmunicipio");
        String query = "insert into funcionarios "+
        "(IDFuncionario,nome,nascimento,cart_trabalho,rg,cpf,endereco,bairro,id_estado,id_municipio,fone,cell,email,funcao,horario,admissao,demissao,obs) VALUE"+
        "(IDFuncionario =?,nome =?,nascimento =?,cart_trabalho =?,rg =?,cpf =?,endereco =?,bairro =?,id_estado =?,id_municipio =?,fone =?,cell =?,email =?,funcao =?,horario =?,admissao =?,demissao =?,obs =?)";
        PreparedStatement stmt = con.prepareStatement(query);
        stmt.setLong(1, idfun);
        stmt.setString(2, jtf_nome.getText());
        stmt.setString(3, nasc);
        stmt.setString(4, jtf_carteira.getText());
        stmt.setString(5, jtf_rg.getText());
        stmt.setString(6, jtf_cpf.getText());
        stmt.setString(7, jtf_endereco.getText());
        stmt.setString(8, jtf_bairro.getText());
        stmt.setLong(9, jcb_estado.getSelectedIndex());
        stmt.setLong(10, idmun);
        stmt.setString(11, jtf_telefone.getText());
        stmt.setString(12, jtf_celular.getText());
        stmt.setString(13, jtf_email.getText());
        stmt.setString(14, jtf_funcao.getText());
        stmt.setLong(15, jcb_horarios.getSelectedIndex());
        stmt.setString(16, admi);
        stmt.setString(17, demi);
        stmt.setString(18, jta_obs.getText());
        stmt.execute();
        }
		/*
		 *  (1IDFuncionario,2nome,3nascimento,4cart_trabalho,5rg,6cpf,7endereco,8bairro,
		 *  9id_estado,10id_municipio,11fone,12cell,13email,14funcao,15horario,16admissao,17demissao,18obs)
		 */
		con.close();
	
		st.close();
	}catch (Exception e) {
		e.printStackTrace();
		JOptionPane.showMessageDialog
		(null,"Erro: \n"+e,"",JOptionPane.INFORMATION_MESSAGE);;
		//System.out.println("erro: \n"+e);
	}
}[/code]

Ele está dizendo que você está tentando inserir um ID duplicado.

Dica, não cadastre ids no braço. No lugar, crie o campo como auto-numerado no banco de dados e use o ID que ele mesmo gerar automaticamente para você. Aí vc nem sequer precisa informar o ID nos seus SQLs, nem mesmo rodar aquela consulta com max ali.
A consulta com o MAX tem um problema. Existe a chance de um registro ser inserido entre a consulta do MAX e o seu INSERT, o que faria seu insert falhar ao tentar inserir um ID duplicado (não é esse seu problema agora, já que vc tá rodando em uma máquina só).

Com a auto-numeração esse problema não ocorre.

Vini

Valeu cara, entendi essa parte do ID autonumerado.

amanha vo configura o tal pra isso, por hora vo deixa esse tópico como resolvido, eu já consegui fazer inserts (rodando o MAX, mas tá inserindo de boa)

só tá dando um problema nos campos de data, mas to quase resolvendo eles, to tirando a mascara deles com o if(strnascimento.contains("/")) bdnasc = strnascimento.replace("/", "");

mas ainda dá erro quando o campo é vazio, nada que eu não resolva, é só acrescenta mais um replace pra tira o place holder xD (ou existe método melhor?)

[code]private void inserir()
{
String strnome = jtf_nome.getText();
String strcart = jtf_carteira.getText();
String strrg = jtf_rg.getText();
String strcpf = jtf_cpf.getText();
String strendereco = jtf_endereco.getText();
String strbairro = jtf_bairro.getText();
String strtelefone = jtf_telefone.getText();
String strcell = jtf_celular.getText();
String stremail = jtf_email.getText();
String strfuncao = jtf_funcao.getText();
int idestado = jcb_estado.getSelectedIndex();
String strmunicipio = (String) jcb_municipio.getSelectedItem();
int idhorario = jcb_horarios.getSelectedIndex();
String strobs = jta_obs.getText();
String strnascimento = jft_nascimento.getText();
String stradmissao = jft_admissao.getText();
String strdemissao = jft_demissao.getText();
String bdnasc = null, bdadmi = null, bddemi = null;
if(strnascimento.contains("/"))
bdnasc = strnascimento.replace("/", “”);
if(stradmissao.contains("/"))
bdadmi = strnascimento.replace("/", “”);
if(strdemissao.contains("/"))
bddemi = strdemissao.replace("/", “”);

	System.out.println(bdnasc);
	try {
		ResultSet rs; 
		Connection con;
		con = gConexao.getConexao();
		
		PreparedStatement st = con.prepareStatement("SELECT idmunicipio FROM municipios WHERE Descrição = ? and IDEstado = ?");
		st.setString(1, strmunicipio);
		st.setLong(2, idestado);
		rs = st.executeQuery();
		rs.next();
		idmun = rs.getInt("idmunicipio");
		System.out.println("idmun: "+idmun);
		
		st = con.prepareStatement("SELECT max(idfuncionario) as id FROM funcionarios");
		rs = st.executeQuery();
		rs.next();
		id = rs.getInt("id")+1;
					
		st = con.prepareStatement("INSERT INTO funcionarios(IDFuncionario, nome, nascimento, cart_trabalho, rg, cpf, endereco, bairro, id_estado, id_municipio, fone, cell, email, funcao, horario, admissao, demissao, obs) Value (?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?)");
		st.setInt(1, id);
		st.setString(2, strnome);
		st.setString(3, bdnasc);
		st.setString(4, strcart);
		st.setString(5, strrg);
		st.setString(6, strcpf);		
		st.setString(7, strendereco);
		st.setString(8, strbairro);
		st.setInt(9, idestado);
		st.setString(10, strmunicipio);
		st.setString(11, strtelefone);
		st.setString(12, strcell);
		st.setString(13, stremail);
		st.setString(14, strfuncao);
		st.setInt(15, idhorario);
		st.setString(16, bdadmi);
		st.setString(17, bddemi);
		st.setString(18, strobs);
		
		
		
		
		
		st.execute();
		
	} catch (FileNotFoundException e) {
		e.printStackTrace();
	} catch (ExcRepositorio e) {
		e.printStackTrace();
	} catch (IOException e) {
		e.printStackTrace();
	} catch (SQLException e) {
		e.printStackTrace();
	}
	
	

}[/code]

aqui o código funcionando, só dando erro quando a data é nula (coisa de vadio ñ tratar isso hj… mas vá lá…)

valeu vinão! já me salvo de algumas nesse fórum! hehehehe :lol: :lol: :lol: :lol:

Para inserir datas, use o setDate.

Primeiro você faz o parse da Data usando um SimpleDateFormatter. Mais ou menos assim:

SimpleDateFormatter df = new SimpleDateFormatter("dd/MM/yyyy"); Date dt = df.parse(strnascimento);

Depois, você transforma num java.sql.Date:

java.sql.Date sqlDate = new java.sql.Date(dt.getTime());

Finalmente, vc substitui o seu set do PreparedStatement:

st.setDate(3, sqlDate);  

Menos linhas, mais fácil de fazer o parse e mais seguro. :slight_smile:

sim, eu já tentei esse método vini, mas eu nunca consegui recuperar as datas do banco pra aplicação com ele… =’(

Ué, no seu banco de dados o tipo da coluna é DateTime?
E você deve usar esse método também na hora de fazer o select, também através de um PreparedStatement.

Essa é a maneira correta de fazer. Via de regra, você sempre deve representar dados pelo seu tipo correto. Datas não são texto, são Date. O único lugar que data vira texto é na view. E textos já não deveriam ser mais datas a partir do momento que passaram pelo seu controller.

ok :wink: