Exception in thread "main" java.lang.NullPointerException (Alterando Base de Dados)

Oi Pessoal, tudo bem? (Desculpe-me pela falta ou erros de acento meu teclado esta bugado)

Sou novo por aqui e novo em programacao. Começando em Java.

Estudo sozinho e achei uma apostila inicial de Java Web. Sei que talvez nao seja o melhor caminho, mas tem me ajudado muito.

Minha duvida é numa alteracao na tabela Contato que náo funciona por causa de um objeto nulo (provavel que seja o ID) que nao consigo resolver. Alguem pode ajudar.

Caso consiga achar alguma resposta nas minhas tentativas eu posto aqui. Nao achei, ainda, um topico que me ajude aqui. (Um portal excelente diga-se de passagem - estou gostando muito e esta me ajudando a remover da cabeça que è impossivel aprender a programar depois de certa indade :slight_smile: )

Erro:

Exception in thread "main" java.lang.NullPointerException
	at br.com.aprendendojava.dao.ContatoDAO.alteraContato(ContatoDAO.java:151)
	at br.com.aprendendojava.jdbc.teste.TestaEdicao.main(TestaEdicao.java:38)

Meu codigo.

import java.sql.SQLException;
import java.text.SimpleDateFormat;
import java.util.List;
import java.util.Scanner;

import br.com.aprendendojava.dao.ContatoDAO;
import br.com.aprendendojava.modelo.Contato;

public class TestaEdicao {

	public static void main(String[] args) throws SQLException {
		// TODO Auto-generated method stub
		
		
		ContatoDAO dao = new ContatoDAO();
		Scanner entrada = new Scanner(System.in);
		SimpleDateFormat dataformatada = new SimpleDateFormat("dd/MM/yyyy");
		
		int pessoa = entrada.nextInt();
		
		List<Contato> contatos = dao.pesquisaID(pessoa);				
		
		for ( Contato contato : contatos) {
			System.out.println("Nome: " + contato.getNome());
			System.out.println("Email: " + contato.getEmail());
			System.out.println("Endereço: " + contato.getEndereco());
			System.out.println("Data de Nascimento: " + dataformatada.format(contato.getDataNascimento().getTime())
			 + "\n");
			}
		
		Contato contato = new Contato();
		
		String nome = entrada.next();

		contato.setNome(nome);
		dao.alteraContato(contato);
		
		/*
		 * for ( Contato contato2 : contatos) { System.out.println("Nome: " +
		 * contato2.getNome()); System.out.println("Email: " + contato2.getEmail());
		 * System.out.println("Endereço: " + contato2.getEndereco());
		 * System.out.println("Data de Nascimento: " +
		 * dataformatada.format(contato.getDataNascimento().getTime()) + "\n"); }
		 */
		
		System.out.print("Resitro alterado com sucesso.");
		
		entrada.close();

	}

}


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 java.util.Calendar;
import java.util.List;

import br.com.aprendendojava.jdbc.ConnectionFactory;
import br.com.aprendendojava.modelo.Contato;

public class ContatoDAO {

	private Connection conexao;
	
	public ContatoDAO() {
		this.conexao = new ConnectionFactory().getConnection();
	}
	
	public static void main(String[] args) {
		// TODO Auto-generated method stub

	}
	
	public void Adiciona(Contato contato) throws SQLException {
		
		// COMANDO SQL PARA INSERIR OS DADOS
		String sql = "insert into contatos " +
				"(nome,email,endereco,dataNascimento) " +
				"values (?,?,?,?)";

		try {
		
		
		// CRIACAO DE UM STATEMENT PARA CAPTAR OS DADOS E INSERIR NA BD
		PreparedStatement stmt = conexao.prepareStatement(sql);

		// Preenche os valores a serem inseridos no banco (????)

		stmt.setString(1, contato.getNome());
		stmt.setString(2, contato.getEmail());
		stmt.setString(3, contato.getEndereco());
		stmt.setDate(4, new Date(contato.getDataNascimento().getTimeInMillis()));
		
		stmt.execute();
		stmt.close();
		
		}
		
		catch (Exception e) {
			// TODO: handle exception
			
			System.out.print(e);
		}
		
		
		finally {
			conexao.close();
		}
		
	}

	
	public List<Contato> getLista() throws SQLException {
		
		try {

			PreparedStatement stmt = this.conexao
					.prepareStatement("select * from contatos");
			ResultSet rs = stmt.executeQuery();
			List<Contato> contatos = new ArrayList<Contato>();
			while (rs.next()) {
				// criando o objeto Contato
				Contato contato = new Contato();
				contato.setNome(rs.getString("nome"));
				contato.setEmail(rs.getString("email"));
				contato.setEndereco(rs.getString("endereco"));
				// montando a data através do Calendar
				Calendar data = Calendar.getInstance();
				data.setTime(rs.getDate("dataNascimento"));
				contato.setDataNascimento(data);
				// adicionando o objeto à lista
				contatos.add(contato);
			}
			rs.close();
			stmt.close();
			return contatos;
		} catch (SQLException e) {
			throw new RuntimeException(e);
		}
	}


	public List<Contato> pesquisaID(int id) throws SQLException{
		
		
		try {

			Contato contato = new Contato();

			String sql = "Select * from contatos"
					+ "	where id = ?";

			PreparedStatement stmt = this.conexao.prepareStatement(sql);

			List<Contato> contatos = new ArrayList<Contato>();			

			stmt.setInt(1,id);

			ResultSet resultado = stmt.executeQuery(); 

			if(resultado.next()){

				contato.setNome(resultado.getString("nome"));
				contato.setEmail(resultado.getString("email"));
				contato.setEndereco(resultado.getString("endereco"));
				// montando a data através do Calendar
				Calendar data = Calendar.getInstance();
				data.setTime(resultado.getDate("dataNascimento"));
				contato.setDataNascimento(data);
				// adicionando o objeto à lista
				contatos.add(contato);

				
			}
			
			return contatos;
		}
		catch (Exception e) {
			// TODO: handle exception
			throw new RuntimeException(e);
		}
	}

	
	public void alteraContato(Contato contato) {
		

		String sql = "update contatos set nome=?, email=?, endereco=?," +
				"dataNascimento=? where id=?";
		
		try {
			PreparedStatement stmt = conexao.prepareStatement(sql);
			stmt.setString(1, contato.getNome());
			stmt.setString(2, contato.getEmail());
			stmt.setString(3, contato.getEndereco());
			stmt.setDate(4, new Date(contato.getDataNascimento()
					.getTimeInMillis()));
			stmt.setLong(5, contato.getId());
			stmt.execute();
			stmt.close();
		} catch (SQLException e) {
			throw new RuntimeException(e);
		}

	}

}

As convenções de nomes do java definem:

  • Classes começam com letra maiúscula e segue o padrão CamelCase.
  • Métodos e atributos começam com letras minúsculas e seguem o padrão camelCase.

Isso melhora a leitura, não tem fins práticos para a compilação, porém, é importante conhecer e aplicar boas práticas.

Eu não gosto dessa abordagem. Eu prefiro abrir a conexão a cada método e fechá-la o mais rápido possível, liberando recursos que não estão em uso.
Lembre-se, o banco de dados é um recurso finito e limitado. Manter conexões abertas sem necessidade, pode trazer sérios problemas.

Sobre o erro: o que tem na linha 151 da classe ContatoDAO?

2 curtidas

Eu geralmente faço assim (exemplo):

public static List<bean.Raca> pesquisar() throws SQLException{
	List<bean.Raca> racas = new ArrayList<>();
	
	try(Connection conectaBancoDeDados = ConectaBancoDeDados.getConexao()){
		String stringSQLPesquisa = "SELECT * FROM Racas "
				+ "ORDER BY Racas.codigo_raca";
		
		try(PreparedStatement pstmt = conectaBancoDeDados
				.prepareStatement(stringSQLPesquisa)){
			
			try(ResultSet rstSet = pstmt.executeQuery()){
				while(rstSet.next()){
					bean.Raca raca = new bean.Raca();
					raca.setCodigoRaca(rstSet.getLong("codigo_raca"));
					raca.setCasta(rstSet.getString("casta"));
					raca.setEspecie(rstSet.getString("especie"));
					raca.setNomeRaca(rstSet.getString("nome_raca"));
					raca.setAlternativa(rstSet.getString("alternativa"));
					
					racas.add(raca);
				}
			}
		}
	}
	return racas;
}

Ao usar try-with-resource, os recursos são liberados automaticamente conforme descrito em Java Tutorials:

A instrução try-with-resources é uma instrução try que declara um ou mais recursos. Um recurso é um objeto que deve ser fechado após a conclusão do programa. A instrução try-with-resources garante que cada recurso seja fechado no final da instrução.

Muito obrigado pela resposta e pelos conselhos de padronizaçao. Estou tentando manter o padrao conforme vou aprendendo.

public void alteraContato(Contato contato) {
		

		String sql = "update contatos set nome=?, email=?, endereco=?," +
				"dataNascimento=? where id=?";
		
		try {
			PreparedStatement stmt = conexao.prepareStatement(sql);
			stmt.setString(1, contato.getNome());
			stmt.setString(2, contato.getEmail());
			stmt.setString(3, contato.getEndereco());
			stmt.setDate(4, new Date(contato.getDataNascimento()
					.getTimeInMillis())); // LINHA 151
			stmt.setLong(5, contato.getId());
			stmt.execute();
			stmt.close();
		} catch (SQLException e) {
			throw new RuntimeException(e);
		}

	}

}

Ao usar try-with-resource, os recursos são liberados automaticamente conforme descrito em Java Tutorials:

Eu li um pouco sobre isso, porém como nao defini fazer o uso pq achei que precisava entender melhor o conceito basico do JAVA. Mas me chamou muita a atencao para a seguranca e certeza de que os objetos serao fechados. Vou estudar mais, obrigado.

O getDataNascimento() está retornando null, aí não tem como invocar o getTimeInMillis().

Importante:
Só utilize chamadas encadeadas de métodos quando você tem a certeza de que os métodos da cadeia nunca vão retornar null.
Se você não tem essa certeza, use variáveis locais e verifique se estão inicializadas.

Entendi @staroski . Eu percebi no debugg que toda a entidade vem vazia. Mas nao entendi por que. o que achei foi que eu perco o id da entidade no meio do processo.

Estou tentando validar isso e posto o codigo. Obrigado.