Date, Time ou Timestamp ... a hora volta 00:00:00 mesmo estando gravada corretamente no banco MySQL
12 respostas
G
Giovanni_Biffi
Boa tarde!
Estou resgatando uma data no banco de dados MySQL e utilizando SimpleDateFormat para formata-la. Acesso o banco e a data está gravada corretamente
Ex.
No banco >>> 2010-03-07 16:39:22
Quero resgatar assim >>> 07/03/2010 16:39:22
Estou utilizando o código abaixo para o resgate, entretanto a hora sempre fica zerada
07/03/2010 00:00:00
Onde estou errando?? Já usei Time, Timestamp e Date… não funciona!
Obrigado!
/* Cria o objeto "listadao" com o método ListaContato() * referênciando a classe ListaContato */ListaContatolistadao=newListaContato();/* Cria a lista com a interface List<> pertencente * a classe java.sql.List usando a classe Contato * como parâmetro. Usa o objeto "listadao" para * recuperar com o método getLista() os "dados" */List<Contato>dados=listadao.getLista();/* usa o for com parâmetro a classe Contato * dado para dados ou seja para o numero de dados * igual a dado continue. */for(Contatodado:dados){System.out.println("Nome: "+dado.getNome());System.out.println("Endereço: "+dado.getEndereco());System.out.println("Email: "+dado.getEmail());Datedata=newDate(dado.getData().getTimeInMillis());SimpleDateFormatsdf=newSimpleDateFormat("dd/MM/yyyy HH:mm:ss");StringdataFormatada=sdf.format(data);System.out.println("Data: "+dataFormatada+"\n");
Creio que o problema não seja na formatação. É mais provável que seja na persistência.
De qualquer forma:
Imprima o valor de dado.getData().getTimeInMillis() e coloque aqui para vermos.
Coloque também o método getLista da classe ListaContato para vermos.
G
Giovanni_Biffi
/* * To change this template, choose Tools | Templates * and open the template in the editor. */packagebr.com.caelum.jdbc;importjava.sql.Connection;importjava.sql.PreparedStatement;importjava.sql.ResultSet;importjava.sql.SQLException;importjava.util.ArrayList;importjava.util.Calendar;importjava.util.List;/** * * @author Biffi */publicclassListaContato{/* faz conexão privada com o banco de dados usando a variável connection * e utilizando a classe java.sql.Connection */privateConnectionconnection;publicListaContato(){// Objeto de conexãothis.connection=newConnectionFactory().getConnection();}/* usando List<contato> que é uma interface de saída em * lista que pertence a classe java.util.List criamos * o método getLista que retornará a lista do banco de * dados conforme o comando quey. */publicList<Contato>getLista(){try{/* cria o objeto contatos no qual é armazenado * o retorno do comando query usando mais uma * intarfece da classe java.util.List ArrayList<> * a qual pega os valores e armazena no vetor. */List<Contato>dados=newArrayList<Contato>();/* cria objeto "stmt" onde são armazados os valores que serão * retornados do banco de dados utilizando o método * prepareStatemente("QUERY SQL") que pertence a classe * java.sql.PreparedStatemente que usa o objeto "connection" * que é responsável pela conexão com o banco de dados */PreparedStatementstmt=this.connection.prepareStatement("select * from contatos");/* Armazena no objeto "rs" os resultados das colunas da tabela * que esttão no objeto "stmt" usando a interface * ResultSet que pertence a classe java.sql.ResultSet * usando o método executeQuery() que pertence ao main Java */ResultSetrs=stmt.executeQuery();/* Enquando ouver colunas continue exibindo resultados * é o que faz o while() passando como método as colunas * armazenadas no objeto "rs" com o método next() que pertence * ao main Java */while(rs.next()){/* criando o objeto contato através do método * Contato() que referência a classe Contato. */Contatodado=newContato();/* Armazenando o nome das colunas cujo os dados * devem ser retornados */dado.setNome(rs.getString("nome"));dado.setEmail(rs.getString("email"));dado.setEndereco(rs.getString("endereco"));/* Montando o retorno de data através da classe * java.util.Calendar */Calendardata=Calendar.getInstance();data.setTime(rs.getDate("data"));dado.setData(data);/* Adicionando o objeto contato a lista * List<contato> contatos ou seja adiociona * o resultado do objeto contato em contatos * que são todos os valores de contato */dados.add(dado);}// fecha while/* encerra o objeto "rs" de ResultSet que retornou * os dados do comando SQL */rs.close();/* encerra o objeto "stmt" de PreparedStatement que * armazenou os dados do comando SQL */stmt.close();/* retorna a variável contatos na qual foi add cada contato * através do while */returndados;}// fim do trycatch(SQLExceptione){thrownewRuntimeException(e);}// fim do catch}// fim do método getLista}// fim da classe lista
G
Giovanni_Biffi
1. Imprima o valor de dado.getData().getTimeInMillis() e coloque aqui para vermos.
O valor é >> 1267930800000
M
marcobiscaro2112
O problema não é na formatação. O valor 1267930800000 se refere mesmo a uma data com hora 00:00.
Isso significa que o problema está na classe de persistência.
Antes da linha 84 da classe que você colocou acima, adicione:
Ou seja: a data resgatada realmente se refere a uma data com horário 00:00. Tem certeza que no banco o valor está certo? Esse valor foi inserido manualmente por você ou foi inserido através do seu programa?
G
Giovanni_Biffi
Foi inserido através do programa:
Principal
/* * To change this template, choose Tools | Templates * and open the template in the editor. */packagebr.com.caelum.jdbc;importjava.sql.Date;importjava.sql.SQLException;importjava.text.SimpleDateFormat;importjava.util.Calendar;importjava.util.List;/** * * @author Biffi */publicclassTestaConexao{publicstaticvoidmain(String[]args)throwsSQLException{/* Cria o objeto "contato" e utiliza método Contato() para referenciar a classe Contato onde estão os gets e sets : Javabeans que são classes que possuem construtor sem argumentos e métodos de acesso tipo get e set */Contatocontato=newContato();/* armazena os dados do contato utilizando o método set para cada tipo de dados */contato.setNome("Tatiane Barreto");contato.setEmail("[email removido]");contato.setEndereco("Rua Arnaldo de Matos, 311");/* Utiliza a classe java.util.Calendar e usa o método getInstance() que retorna a instância do objeto */contato.setData(Calendar.getInstance());/* cria o objeto "dao" e utiliza o método ContatoDAO() para referênciar a classe ContatoDAO */ContatoDAOdao=newContatoDAO();/* o objeto "dao" é processado pelo método adiciona() que pertence a classe ContatoDAO() enviando como parâmetro o objeto "contato" sendo assim os objetos recebem as seguintes funções: contato >> armazenar valores dao >> trânsportar os valores de contato até o método adiciona*/dao.adiciona(contato);// imprime somente o textoSystem.out.println("Gravado!");/* Cria o objeto "listadao" com o método ListaContato() * referênciando a classe ListaContato */ListaContatolistadao=newListaContato();/* Cria a lista com a interface List<> pertencente * a classe java.sql.List usando a classe Contato * como parâmetro. Usa o objeto "listadao" para * recuperar com o método getLista() os "dados" */List<Contato>dados=listadao.getLista();/* usa o for com parâmetro a classe Contato * dado para dados ou seja para o numero de dados * igual a dado continue. */for(Contatodado:dados){System.out.println("Nome: "+dado.getNome());System.out.println("Endereço: "+dado.getEndereco());System.out.println("Email: "+dado.getEmail());Datedata=newDate(dado.getData().getTimeInMillis());SimpleDateFormatsdf=newSimpleDateFormat("dd/MM/yyyy HH:mm:ss");StringdataFormatada=sdf.format(data);System.out.println("Data: "+dado.getData().getTimeInMillis()+"\n");}// fim for}}
Classe que insere
/* * To change this template, choose Tools | Templates * and open the template in the editor. */packagebr.com.caelum.jdbc;importjava.sql.Connection;importjava.sql.PreparedStatement;importjava.sql.SQLException;importjava.sql.Timestamp;/** * * @author Biffi */publicclassContatoDAO{/* DAO : Data Access Object, é um padrão para persistência de dados que permite separar regras de negócio das regras de acesso a banco de dados. Numa aplicação que utilize a arquitetura MVC, todas as funcionalidades de bancos de dados, tais como obter as conexões, mapear objetos Java para tipos de dados SQL ou executar comandos SQL, devem ser feitas por classes de DAO. */// Faz conexão privada com o banco usando a variável privada connection.privateConnectionconnection;/* o método ContatoDAO() cria um objeto "connection" de conexão usando a classe ConnectionFactory na qual existe o método getConnection() */publicContatoDAO(){// Objeto de conexãothis.connection=newConnectionFactory().getConnection();}publicvoidadiciona(Contatocontato){//Comando SQL é declarado com StringStringsql="insert into contatos"+"(nome, email, endereco, data)"+"values (?,?,?,?)";/* cria objeto "stmt" onde são armazados os valores que serão incluidos no banco de dados utilizando o método prepareStatemente(sql) que pertence a classe java.sql.PreparedStatemente que usa o objeto "connection" que é responsável pela conexão com o banco de dados */try{PreparedStatementstmt=connection.prepareStatement(sql);/* seta os valores para incluir no objeto "stmt" ou seja dá localização e valor diferente para cada ponto de interrogação do comando SQL */stmt.setString(1,contato.getNome());stmt.setString(2,contato.getEmail());stmt.setString(3,contato.getEndereco());/* formata valor de data para a compreensão do banco de dados utilizando o método Date() pertencente a classe java.sql.Date */stmt.setTimestamp(4,newTimestamp(contato.getData().getTimeInMillis()));/* Inicia e encerra a execução do objeto "stmt" utilizando os métodos execute() e close() pertencentes a classe main do java */stmt.execute();stmt.close();}catch(SQLExceptione){/* trata erros de conexão clausula adiciona automaticamente no PreparedStatement na instrução stmt.close() */thrownewRuntimeException(e);}}}
Classe Set e Get
/* * To change this template, choose Tools | Templates * and open the template in the editor. */packagebr.com.caelum.jdbc;importjava.sql.Date;importjava.util.Calendar;/** * * @author Biffi */publicclassContato{/* Classe responsável por armarzenar e recuperar as informações do banco de dados usando os métodos set( função: armarzenar ) e get( função: recuperar) para cada variável. */privatelongid;privateStringnome;privateStringemail;privateStringendereco;privateCalendardata;publicCalendargetData(){returndata;}publicvoidsetData(Calendardata){this.data=data;}publicStringgetEmail(){returnemail;}publicvoidsetEmail(Stringemail){this.email=email;}publicStringgetEndereco(){returnendereco;}publicvoidsetEndereco(Stringendereco){this.endereco=endereco;}publiclonggetId(){returnid;}publicvoidsetId(longid){this.id=id;}publicStringgetNome(){returnnome;}publicvoidsetNome(Stringnome){this.nome=nome;}}
M
marcobiscaro2112
O campo “data” do banco é de que tipo?
G
Giovanni_Biffi
DATETIME no MySQL
G
Giovanni_Biffi
M
marcobiscaro2112
Pois é… um campo do tipo DATE armazena só a data (sem horário).
No método getLista você viu como você pega o campo “data”? Com o método getDate de PreparedStatement.
Isso quer dizer que na hora de resgatar ele está interpretando o campo como se fosse DATE.
A solução? Troque sua linha 84 por:
data.setTime(rs.getTimestamp("data"));
Isso fará que ele interprete como TIMESTAMP (ou DATETIME) considerando o horário.
Última coisa: a classe DAO serve tanto para inserir como para resgatar dados. O método getLista() deveria estar nela e a classe ListaContato nem precisaria existir.
G
Giovanni_Biffi
MUITO OBRIGADO! ficou perfeito agora… criei a classe ListaContato para separar a “listagem” da “inclusão”, não sei se é correto mas acho que permite uma manutenção mais objetiva talvez… comecei a estudar Java agora e estou estudando uma apostila da Caelum e o livro Java Como Programar 6ª Edição… não entendo tudo bem claramente, como se dá as comunicações e o funcionamento das classes existentes. Agradeço por ter utilizado o seu tempo para me ajudar…