Java + SQL e parseamento de datas

39 respostas
T

Bom dia.

Estou com uma dúvida.

Tenho um campo no meu banco como datetime, preciso fazer um Update na tabela…
Problema: Como enviar a data no formato correto para o banco?

Datetime me retorna : 2011-01-26 hh:mm:ss.mmm
Queria algo neste formato para enviar ao banco!!

Como faço isso ?

39 Respostas

drsmachado

Não tá usando hibernate, né?
Dependendo o banco de dados, caso vc passe como argumento a função “now()”, estará informando a data e hora atuais.
Sei que no oracle não funciona (a função tem outro nome)

eltonads

Bom… Você pode usar um DateFormat da vida, se você está escrevendo os SQLs na mão, apenas com Strings…
Mas acho que se você usar um PreparedStatement, você só precisa usar um stmt.setDate(…) e pronto.

Att.,

T

É bom postar o código né :slight_smile:
Desculpem!!

Segue o código do método da classe que manipula a inserção:

public void InsereResultado() {

        String comando = "Update tblRegistro Set Resultado = ? AND Situacao = ? Where ProtocoloID = '"+ form.getProtocolo() +"'";

        PreparedStatement p;
        try {

            p = this.cx.fazConexao().prepareStatement(comando);
            p.setString(1, form.getResultado());
            p.setString(2, "2");

            p.execute();



        } catch (SQLException e) {
            e.printStackTrace();
        }
    }

Eu tinha feito uma trigger no banco, mas devido a outra que eu já criei, ele dispara automático e não quero isso!!
Eu quero atualizar também o campo dataFinal que é um datetime e está NULL no banco…

T

Alguém sabe?

T

Ajuda ae!!

drsmachado

Você está alterando o código, certo?
Qual o banco de dados?
Você pode usar, como dito pelo eltonads, um dateformat ou qubrar na mão mesmo e inserir.
Se a data a ser inserida, na atualização, é a atual, coloca logo um now() e pronto.

T

Criar método now() em Suporte.Login

o.O

importo algo?

T

Na verdade tenho este modificador:

String formato = "yyyy-MM-dd HH:mm:ss.SSS";
        SimpleDateFormat formatter = new SimpleDateFormat(formato);
        System.out.println("A data formatada é: " + formatter.format(form.getDataFinal()));

O meu Update é esse:

String comando = "Update tblRegistro Set Resultado = ?, Situacao = '2' Where ProtocoloID = ?";

Precisaria adicionar um campo para atualizar que é data e está no formato: yyyy-MM-dd HH:mm:ss.SSS
Como eu insiro isso no meu ‘comando’??

Segue o código do método todo:

public void InsereResultado() {


        String formato = "yyyy-MM-dd HH:mm:ss.SSS";
        SimpleDateFormat formatter = new SimpleDateFormat(formato);
        System.out.println("A data formatada é: " + formatter.format(form.getDataFinal()));


        String comando = "Update tblRegistro Set Resultado = ?, Situacao = '2' Where ProtocoloID = ?";

        try {
            PreparedStatement stmt = cx.fazConexao().prepareStatement(comando);
            stmt.setString(1, form.getResultado());
            stmt.setInt(2, form.getProtocolo());
           

            stmt.execute();
            stmt.close();
            JOptionPane.showMessageDialog(null, "Resultado inserido corretamente!");


        } catch (SQLException e) {
            e.printStackTrace();
            JOptionPane.showMessageDialog(null, "Resultado não inserido!\n\nConsulte o chamado e insira novamente.");
        }
    }
drsmachado
SQL basiquinho - Update:

Quando você executa um update, como está ali na query, precisa passar:

1 - o nome da coluna que será atualizada;

2 - o novo valor da coluna;

3 - cláusula where, indicando qual índice deverá ser alterado, caso contrário, todos os registros serão;

Sua query diz que as colunas resultado e situação serão anteradas enquanto o protocoloid é o que foi selecionado. Deve existir um campo com o nome data, suponhamos que ele seja dataAtual:

//código para converter a data aqui
//mais código aqui se preciso
 String comando = "Update tblRegistro Set Resultado = ?, Situacao = '2', dataAtual = ? Where ProtocoloID = ?";  
   
         try {  
             PreparedStatement stmt = cx.fazConexao().prepareStatement(comando);  
             stmt.setString(1, form.getResultado());  
stmt.setString(2, sua_variavel_com_a_nova_data_aqui);
             stmt.setInt(3, form.getProtocolo());  
   
             stmt.execute();  
             stmt.close();  
             JOptionPane.showMessageDialog(null, "Resultado inserido corretamente!");  
   
   
         } catch (SQLException e) {  
             e.printStackTrace();  
             JOptionPane.showMessageDialog(null, "Resultado não inserido!\n\nConsulte o chamado e insira novamente.");  
         }
T

Siiim, sim…O problema não é bem este!!

Vamos lá:

Eu criei o formatador, ele formata a data ATUAL corretamente do jeito que eu quero inserir.
O problema é:

Como eu insiro isso no banco?
Se eu coloco formatter.format(data) no meu update ele não vai.
Se eu coloco data2 = formatter.format(data); e insiro data2 no meu update ele não vai também
O formato está correto, Update tá tranquilo, o problema está em COMO inserir a data!!

Como eu digo, em linhas de código =D

drsmachado

Converte em uma string e insere na query

pmlm

Não. Insere como Date mesmo e não precisas de te preocupar com o formato.

drsmachado

A query é uma string, é isso que o banco vai receber como parâmetro. Independente do tipo de dados que você tem, o BD só vai saber do que se trata quando fizer a leitura do comando.
Acontece que se você passa a data formatada com o padrão brasileiro (dd/MM/yyyy) o BD não reconhece isto.
Se você instancia um objeto do tipo Date(), ele estará formatado da seguinte forma:

public static void main(String args[]){
        Date d = new Date();
        System.out.println(d);
    }

cuja saída seria:

Mon Jan 31 15:24:27 BRST 2011

O BD não compreende do que se trata, simplesmente irá retornar erro.

Por isso a necessidade de formatar a data para um pattern mais “ajeitado”.

pmlm

Errado.

Datas devem ser inseridas como Date na DB exactamente para evitar os problemas do formato. Mais ou menos assim:

public void InsereResultado() {  
      
    String comando = "Update tblRegistro Set Resultado = ?, Situacao = ?, dataFinal = ? Where ProtocoloID = ?";  
      
    PreparedStatement p;  
 
   String formato = "yyyy-MM-dd";  // Formato no FORM  
   SimpleDateFormat formatter = new SimpleDateFormat(formato);  
   Date dataFinal = formatter.parse(form.getDataFinal()):

   try {  
      
            p = this.cx.fazConexao().prepareStatement(comando);  
            p.setString(1, form.getResultado());  
            p.setString(2, "2");  
            p.setDate(3, new java.sql.Date(dataFinal.getTime()));
            p.setString(4, form.getProtocolo();
     
            p.execute();  
     
     } catch (SQLException e) {  
           e.printStackTrace();  
     }  
}
T

pmlm, valeu cara…
Mas olha o que deu!!

Cannot find symbol.
method parse(java.util.Date)
location: class java.text.SimpleDateFormat

Da esse erro.

O código ficou assim, após eu mudar apenas algumas coisinhas para se adequar ao meu necessário:

public void InsereResultado() {

        String comando = "Update tblRegistro Set Resultado = ?, Situacao = ?, dataFinal = ? Where ProtocoloID = ?";

    PreparedStatement p;

   String formato = "yyyy-MM-dd HH:mm:ss.SSS";  // Formato no FORM
   SimpleDateFormat formatter = new SimpleDateFormat(formato);
   Date dataFinal = formatter.parse(form.getDataFinal());

   try {

            p = this.cx.fazConexao().prepareStatement(comando);
            p.setString(1, form.getResultado());
            p.setString(2, "2");
            p.setDate(3, new java.sql.Date(dataFinal.getTime()));
            p.setInt(4, form.getProtocolo());

            p.execute();

     } catch (SQLException e) {
           e.printStackTrace();
     }
}
drsmachado

Concordo que datas devem ser inseridas como date e horas e afins com o formato adequado.
Eventualmente há a necessidade de persistir essa informação em um único campo ou, pior, o banco de dados já existe e o “bendito” sujeito que o desenvolveu implicou que seria assim.

drsmachado
Só para complementar, insira estes métodos no teu código e os chame para converter, como coloquei:
public void  InsereResultado() {  
     
           String comando = "Update tblRegistro Set Resultado = ?, Situacao = ?, dataFinal = ? Where protocoloID = ?";  
   
     PreparedStatement p;  
   
    String dataFinal = formatDate(form.getDataFinal());  
   
    try {  
   
             p = this.cx.fazConexao().prepareStatement(comando);  
             p.setString(1, form.getResultado());  
             p.setString(2, "2");  
             p.setDate(3, new java.sql.Date(dataFinal.getTime()));  
             p.setInt(4, form.getProtocolo());  
   
             p.execute();  
   
      } catch (SQLException e) {  
            e.printStackTrace();  
      }  
 }  

public static String formatDate(Date data) {
        return formatDate(data, "yyyy-MM-dd HH:mm:ss:SSS");
    }

    public static String formatDate(Date data, String formato) {
        SimpleDateFormat sdf = new SimpleDateFormat(formato);
        return sdf.format(data);
   }
drigo.angelo

Pelo amor de Deus, não passem datas pro banco como String:!:

O preparedStatement já tem um método set(int, java.sql.Date), como mencionado acima, e é melhor utilizar esse quando for passar a data :slight_smile:

Se você quer passar a hora atual pra sua query: (o resto do código copia do de cima que ta certo)

//Pega a data/hora atual e insere no prepared statement preparedStatement.set(x, new java.sql.Date(new java.util.Date().getTime() ));

T

drigo, bom dia.

Cara, mas e como eu insiro a data FORMATADA do jeito que coloquei lá?
Eu até entendo o que estão dizendo, mas não consigo encontrar uma forma de inserir formatado.

Ele insere com getTime(), insere sem getTime(), mas ele dá erro na inserção, update e afins por que não está no formato correto.

Como eu insiro isso formatado? :open_mouth:

drsmachado

Como está o campo na tabela do banco de dados?
Como date? Datetime?

T

drsmachado

Dá o seguinte erro na linha:

p.setDate(3, new java.sql.Date(dataFinal.getTime()));

cannot instantiate Date(long) at java.sql.Date to ()

Datetime, retornando 2010-02-01 09:07:28:367

neste formato!

drsmachado

Sim, datetime é este formato.
Tentou da forma que eu postei antes?

drigo.angelo

Não entendi. :frowning:

Você não insere formatado, a idéia de formatar é justamente para exibição, você não vai exibir seus dados no banco, ou vai ? :shock:

O banco apenas “guarda” a informação que foi no dia tal, as tal horas/minutos/segundos/etc o formato que as informações estão no banco não devem interferir em nada, até porque diferentes bancos formatam datas/dados de diferentes maneiras e quanto menos você (você = sua aplicação) se importa em como os dados estão representados no banco, mais flexível sua aplicação fica (só pra constar, flexibilidade é bom ).

Na hora que você for exibir a data que ela deve ser formatada :smiley:

[]'s

N

Bom Dia Thiago, não sei até que ponto é viavel você utilizar a classe calendar para fazer isso…

Eu acredito que seja mais interessante… Bom fica a minha sugestão…

Abraço

T

Bom…

Se você tem um date por exemplo no banco e insere no banco um GETDATE() ele não aceita.
O formato retornado pelo GETDATE() é diferente.

No java retorna Tue Feb 01 09:12:33 GMT -03:00 2011

Se você tentar no banco:

insert into tblRegistro (dataFinal) values (Tue Feb 01 09:12:33 GMT -03:00 2011)
ou até mesmo …values (“Tue Feb 01 09:12:33 GMT -03:00 2011”)

Ele te retorna um erro de incompatibilidade de formatos.
Tendo tudo isso em vista, este é o motivo para o qual eu preciso da data SAINDO corretamente no Banco, para não precisar ficar criando triggers no Banco para inserir a data correta, entendeu?
Se eu mandar isso do Java para o Banco ele da erro no banco e não insere nada.

drsmachado

drigo.angelo:
Não entendi. :frowning:

Você não insere formatado, a idéia de formatar é justamente para exibição, você não vai exibir seus dados no banco, ou vai ? :shock:

O banco apenas “guarda” a informação que foi no dia tal, as tal horas/minutos/segundos/etc o formato que as informações estão no banco não devem interferir em nada, até porque diferentes bancos formatam datas/dados de diferentes maneiras e quanto menos você (você = sua aplicação) se importa em como os dados estão representados no banco, mais flexível sua aplicação fica (só pra constar, flexibilidade é bom ).

Na hora que você for exibir a data que ela deve ser formatada :smiley:

[]'s

Desculpe drigo.angelo, mas a data a ser inserida é informada pelo usuário ou o sistema pega a data atual.
Bem, sendo assim, como você “guarda” a data atual? Passando direto um new Date()?
Ou você força o usuário a digitar a data no formato ISO, apenas para não convertê-la?
O usuário vai informar a data no formato que ele reconhece como tal (no caso do Brasil, dd/MM/yyyy), não?
Se eu informar isso ao banco de dados, qualquer que seja ele, ele vai entender como erro (a não ser que estejamos passando para uma procedure que esteja apta a converter, aí é outro esquema… Aliás, poderíamos até passar símbolos quânticos que não haveria problemas).

Código bonitiho, sim, nos padrões, ótimo.
Mas o nosso amigo não consegue inserir o dado.
Se é string ou não, se é uma árvore binária ou rubro negra, tanto faz, resolve o problema?

T

Vamos fazer assim, diferente!!!

Como executo procedure pelo Java?

Criei a Procedure que faz isso, já tenho os parâmetros, como executo ela?
Ficou assim o código…mas não é asssim, creio eu!

public void InsereResultado() {


        String coman_proc = "exec AtualizaDataFinal (?,?,?)";
        PreparedStatement p;



        try {

            p = this.cx.fazConexao().prepareStatement(coman_proc);
            p.setString(1, form.getResultado());
            p.setString(2, "2");
            p.setInt(3, form.getProtocolo());

            p.execute();

        } catch (SQLException e) {
            e.printStackTrace();
        }
    }
drigo.angelo

Então acho que eu entendi o problema errado, como eu disse :frowning:

Pra inserir uma data no banco, utilize o método set(int, java.sql.Date) do preparedStatement

Se você sabe o formato que o usuário digitou, pode converter a String pra um objeto do tipo java.util.Date utilizando o método parse do SimpleDateFormat, igual você fez acima

Se for sempre pegar a data atual (sempre no sentido de todas as vezes que passar em um trecho específico do código) é melhor criar um new java.util.Date, que pega a data atual do sistema

Isso funciona e é “bonitinho” dentro dos padrões, só pensei que ele queria que no banco de dados os dados ficassem representados de uma maneira específica e queria ajustar isso na aplicação, tipo “quero que no banco de dados, as datas fiquem no formato ‘DD/MM/YYYY-HH:MM:SS.MMMM’, daí eu crio um campo do tipo varchar(24) e formato a data na aplicação toda vez que for inserir uma data, insiro como uma String” isso eu acho errado

Desculpe o transtorno, foi pq eu entendi errado…

[]'s

drigo.angelo

Pra executar a procedure depende do SGBD, no caso do postgress você teria que mudar o coman_proc = “exec AtualizaDataFinal (?,?,?)”; pra coman_proc = “SELECT AtualizaDataFinal (?,?,?)”;

drsmachado

Você já está usando preparedStatement, então, a chamada, caso seja o banco de dados MySQL é

String coman_proc = "CALL AtualizaDataFinal (?,?,?)";

Cada BD vai ter um diferente…

T

SQL Server.

Eu coloquei de uma forma que encontrei aqui, mas não deu não!! =x
Tá dificil, hein…

Acho que pra fazer o software todo não apanhei tanto, quanto esta data!!

pmlm
Thiago0803:
pmlm, valeu cara... Mas olha o que deu!!

Cannot find symbol.
method parse(java.util.Date)
location: class java.text.SimpleDateFormat

Da esse erro.

O código ficou assim, após eu mudar apenas algumas coisinhas para se adequar ao meu necessário:
public void InsereResultado() {

        String comando = "Update tblRegistro Set Resultado = ?, Situacao = ?, dataFinal = ? Where ProtocoloID = ?";

    PreparedStatement p;

   String formato = "yyyy-MM-dd HH:mm:ss.SSS";  // Formato no FORM
   SimpleDateFormat formatter = new SimpleDateFormat(formato);
   Date dataFinal = formatter.parse(form.getDataFinal());

   try {

            p = this.cx.fazConexao().prepareStatement(comando);
            p.setString(1, form.getResultado());
            p.setString(2, "2");
            p.setDate(3, new java.sql.Date(dataFinal.getTime()));
            p.setInt(4, form.getProtocolo());

            p.execute();

     } catch (SQLException e) {
           e.printStackTrace();
     }
}
form.getDataFinal() já é um date? Nesse caso, podes tirar as três linhas antes do try e mudar só a linha do setDate para:
p.setDate(3, new java.sql.Date(form.getDataFinal().getTime()));
T

Código ficou:

public void InsereResultado() {


        //String coman_proc = "exec AtualizaDataFinal (?,?,?)";




        String coman_proc = "CALL AtualizaDataFinal (?,?,?)";
        PreparedStatement p;



        try {

            p = this.cx.fazConexao().prepareStatement(coman_proc);
            p.setString(1, form.getResultado());
            p.setString(2, "2");
            p.setInt(3, form.getProtocolo());

            p.execute();

        } catch (SQLException e) {
            e.printStackTrace();
        }

    }
Deu os seguinte erros:

com.microsoft.sqlserver.jdbc.SQLServerException: Incorrect syntax near @P0.

at com.microsoft.sqlserver.jdbc.SQLServerException.makeFromDatabaseError(SQLServerException.java:156)

at com.microsoft.sqlserver.jdbc.SQLServerStatement.getNextResult(SQLServerStatement.java:1373)

at com.microsoft.sqlserver.jdbc.SQLServerPreparedStatement.doExecutePreparedStatement(SQLServerPreparedStatement.java:371)

at com.microsoft.sqlserver.jdbc.SQLServerPreparedStatement$PrepStmtExecCmd.doExecute(SQLServerPreparedStatement.java:322)

at com.microsoft.sqlserver.jdbc.TDSCommand.execute(IOBuffer.java:4003)

at com.microsoft.sqlserver.jdbc.SQLServerConnection.executeCommand(SQLServerConnection.java:1550)

at com.microsoft.sqlserver.jdbc.SQLServerStatement.executeCommand(SQLServerStatement.java:160)

at com.microsoft.sqlserver.jdbc.SQLServerStatement.executeStatement(SQLServerStatement.java:133)

at com.microsoft.sqlserver.jdbc.SQLServerPreparedStatement.execute(SQLServerPreparedStatement.java:304)
drsmachado

Desculpa cara, acabei esquecendo.

Você vai precisar do CallableStatement e não do preparedStatement.

Aqui tem um exemplo

http://www.java2s.com/Code/Java/Database-SQL-JDBC/CallStoredProcedureInMySql.htm

T

Eu uso

cs.registerOutParameter(1, java.sql.Types.INTEGER);

ou não?
Utilizo SQL Server e isso é de MySQL, não sei se é mesma sintaxe, é?

drsmachado

Aí vai um exemplo para SQLServer
http://www.javadb.com/connect-to-database-and-call-stored-procedure
E aqui:
http://onjava.com/pub/a/onjava/2003/08/13/stored_procedures.html?page=1
http://onjava.com/pub/a/onjava/2003/08/13/stored_procedures.html?page=2

T

Esquece!!

Não consigo, não está indo de jeito nenhum!!
Já tinha visto este site e tentei.

…valeu pela ajuda, mas depois de 1 semana tentando eu desisto!

uahuahau…

drsmachado

Depois de uma semana, desistir?
Se a questão é só formato da data, bem, joga como String mesmo e acabou.

T

Desistir desta etapa do programa :slight_smile:

Vou fazer alguns outros ajustes que precisam ser feitos ainda e mais pra frente eu vejo este problema da data!!

=D

Criado 27 de janeiro de 2011
Ultima resposta 1 de fev. de 2011
Respostas 39
Participantes 6