Utilização de Timestamp

3 respostas
E

Pessoal,

Estou com um probleminha de utilizaação do tipo java.sql.Timestamp:

Crio um objeto para inclusão no banco de dados (estou utilizando no momento DB2 e SQLServer) utilizando java.util.Calendar / GregorianCalendar com a data atual (digamos, 2002-10-18 10:03:35.225).

Ao retornar do banco com Timestamp o valor é sempre diferente (digamos, 2002-10-18 10:03:35.226).

Ao comparar as duas datas - obviamente - elas são diferentes.

Esse problema dos milissegundos é ocasionado aparentemente pela divisão de Timestamp.getNanos() por 1000000, procedimento indicado na documentação (…guide/jdbc/getstart/mapping.html#1007474)

Alguém saberia como tratar desse problema?

Grato.

Edgar

3 Respostas

Paulo_Silveira

Edgar, você poderia colocar aqui o seu trecho de código? Acho que tenho idéia do que pode ser…

E

Aí está o código, Paulo.

Agradeço pela atenção.

// <DateUtils>
  /**
   * Retorna altera o Tipo Timestamp para Calendar
   * @return
   */
  public static java.util.Calendar convertoToCalendar( java.sql.Timestamp data ){
    GregorianCalendar calendario = new GregorianCalendar();
    if ( data.getNanos() > 0) {
      calendario.setTime( new java.util.Date(data.getTime() + data.getNanos()/1000000 ) );
    } else {
      calendario.setTime( new java.util.Date(data.getTime() ) );
    }
    return calendario;
  }

  /**
   * Retorna um Objeto Calendar correspondente a data da máquina
   * @return
   */
  public static Calendar getCalendarCommonDate(){
    Calendar current = new GregorianCalendar();
    Date currentTime = new Date();
    current.setTime( currentTime );
    return current;
  }

  /**
   * Retorna um Objeto Calendar correspondente a data da máquina
   * @return
   */
  public static java.sql.Timestamp convertToSQLDate( Calendar data ){
    return new java.sql.Timestamp( data.getTime().getTime() );
  }
  // </DateUtils>


  // <Acesso ao Banco>
  public ObjVO load(ObjPK pk) throws DAOLoadException{
    if (!(pk instanceof TesteMsgPK)){
      throw new DAOLoadException( "Não é um objeto do tipo esperado" );
    }

    TesteMsgPK testeMsgPK = (TesteMsgPK) pk;
    TesteMsgVO testeMsgVO = new TesteMsgVO();
    PreparedStatement ldStm = null;

    try{
      ldStm = VLstmContainer.getLoadStatement();
      ldStm.setLong(1, testeMsgPK.getId() );

      ResultSet rs = ldStm.executeQuery();
      // A Busca pela chave primaria deve retornar apenas 1 linha.
      rs.next();
      testeMsgVO.setTesteMsgPK(new TesteMsgPK(rs.getLong("ID")));
      testeMsgVO.setDataEntrada(DateUtils.convertoToCalendar(rs.getTimestamp("dataEntrada")));
      testeMsgVO.setCodigoTeste(rs.getString("codigoTeste"));
      testeMsgVO.setDescricao(rs.getString("descricao"));
      testeMsgVO.setXML(rs.getString("xml"));
      testeMsgVO.setTipoXML(rs.getString("tipoXML"));
    }
    catch(SQLException e){
      throw new DAOLoadException(e.getMessage());
    }
    catch(Exception e){
      e.printStackTrace();
    }
    finally {
       try { ldStm.close(); }
       catch (Exception e) {}
    }
    return testeMsgVO;
  }

  public ObjPK save(ObjVO vo) throws DAOSaveException{
    if (!(vo instanceof TesteMsgVO)){
      throw new DAOSaveException("Não é um objeto do tipo esperado");
    }

    TesteMsgVO testeMsgVO = (TesteMsgVO) vo;
    PreparedStatement svStm = null;

    try{
      svStm = VLstmContainer.getSaveStatement();
      svStm.setTimestamp(1,DateUtils.convertToSQLDate(testeMsgVO.getDataEntrada()));
      svStm.setString(2,testeMsgVO.getCodigoTeste());
      svStm.setString(3,testeMsgVO.getDescricao());
      svStm.setString(4,testeMsgVO.getXML());
      svStm.setString(5,testeMsgVO.getTipoXML());
      svStm.setLong(6,testeMsgVO.getTesteMsgPK().getId());

      svStm.executeUpdate();
    }
    catch(SQLException e){
      throw new DAOSaveException(e.getMessage());
    }
    finally {
       try { svStm.close(); }
       catch (Exception e) {}
    }
    return null;
  }
  // </Acesso ao Banco>

  // <Teste com JUnit>
  public void testSave() {
    TesteMsgDAO testeMsgDAO = new TesteMsgDAO(TSTconnection);
    TesteMsgVO  testeMsgVO1 = null;
    TesteMsgVO  testeMsgVO2 = null;
    TesteMsgVO  testeMsgVO3 = null;
    TesteMsgVO  testeMsgVO4 = null;

    Calendar agora = DateUtils.getCalendarCommonDate();
    System.out.println("Save agora : " + DateUtils.calendarToDBDate(agora));

    try{
      testeMsgVO1 = testeMsgDAO.load(new TesteMsgPK(1));
      testeMsgVO2 = testeMsgDAO.load(new TesteMsgPK(1));
    }
    catch(DAOLoadException daol){
      System.out.println(daol.getMessage());
    }

    assertTrue(testeMsgVO2.equals(testeMsgVO1));
    testeMsgVO2.setCodigoTeste("ANOTHER");
    testeMsgVO2.setDataEntrada(agora);

    assertTrue(!(testeMsgVO2.equals(testeMsgVO1)));

    try{
      testeMsgDAO.save(testeMsgVO2);
      testeMsgVO3 = testeMsgDAO.load(testeMsgVO2.getTesteMsgPK());
      testeMsgVO4 = testeMsgDAO.load(testeMsgVO2.getTesteMsgPK());
      System.out.println("Save testeMsgVO3.getDataEntrada() : " + DateUtils.calendarToDBDate(testeMsgVO3.getDataEntrada()));
      System.out.println("Save testeMsgVO4.getDataEntrada() : " + DateUtils.calendarToDBDate(testeMsgVO4.getDataEntrada()));

      assertEquals(testeMsgVO3, testeMsgVO4);

      assertTrue(!testeMsgVO3.equals(testeMsgVO1));
    }
    catch(Exception e){
      assertTrue(false);
    }
  }
  // </Teste com JUnit>
Paulo_Silveira

bem, se eu fosse voce, eu setaria o nanos do dia atual para 0, dessa maneira sempre ia ter 0 no nanos e nao ia dar problema

mas realmente, o problema eh o arredondamento de quando voce fazer o /100000. tente usar o Math.round na divisao, assim:

calendario.setTime(new java.util.Date(data.getTime() + Math.round(data.getNanos()/1000000.0 )));

repare que tem um .0 no final do numero, isso eh para forcar a conta retornar um doube. (ou voce pode fazer um casting no 1000000 para double).

ps: qdo voce faz new GregorianCalendar, ele ja deixa esse calendario no dia atual, voce nao precisa dar um new Date.

Criado 18 de outubro de 2002
Ultima resposta 18 de out. de 2002
Respostas 3
Participantes 2