Inicial > Programação > Como Recuperar a Data Atual do Banco de Dados

Como Recuperar a Data Atual do Banco de Dados

Uma das informações que com alguma frequência preciso é a data e a hora atuais. Você sabe que não podemos confiar na data da máquina do cliente e particularmente considero uma má prática utilizar a data da máquina onde está o servidor de aplicação. O ambiente onde está a aplicação pode ser formado por um cluster onde as máquinas não necessariamente compartilham da mesmas data e hora. Se tempo é crítico para sua apicação, você precisa que ela venha de um local centralizado e confiável.

Não sou fã de utilizar SQL nativo e nem de criar coisas no banco de dados que me retornem alguma informação pontual, como procedures e views, mas se você não tem uma central horária (servidor NTP), o banco de dados acaba se tornando um caminho válido, pois teoricamente há DBAs e um pessoal de infraestrutura cuidando de vários aspectos técnicos desse ambiente, como o hardening, o monitoramento dos processos, o gerenciamento de patches, provisionamento de recursos, etc. É claro que tanto zelo com um servidor tão estratégico dá crédibilidade às informações que queiramos extrair de lá.

Vamos utilizar a nossa já conhecida interface ReturningWork para acessar a Connection através da Session do Hibernate* e de lá extrair o nome do banco de dados utilizado consultando a instância de um DatabaseMetadata, que é uma interface implementada pelo fabricante do driver JDBC. Se você sabe qual é o banco de dados, e isso em geral é verdade, não é necessário fazer isso:

   Session hibernateSession = entityManager.unwrap(Session.class);
   String databaseName = hibernateSession.doReturningWork(
      new ReturningWork<String>() {
      @Override
      public String execute(Connection connection) throws SQLException {
         return connection.getMetaData().getDatabaseProductName();
      }
   });

Nesse ponto é interessante que você crie uma enum para mapear a forma de se fazer a consulta que retorna a data em cada um dos SGBDs que você utiliza. Criei uma para o Oracle e outra para o MySQL, mas omiti o método que determina qual é a enum correta assim como os getters:

public enum DBDialect {
   ORACLE("Oracle", 
      "SELECT TO_CHAR(SYSDATE, 'dd/MM/yyyy HH24:mi:ss') FROM DUAL"),
   MYSQL("MySQL", 
      "SELECT DATE_FORMAT(SYSDATE(),'%d/%m/%Y %H:%i:%s')");

   // (...) demais métodos para recuperar o dialeto correto

}

Sabendo o nome do banco de dados, podemos utilizar a sintaxe de consulta correta para extrair a data através de uma Native Query:

   DBDialect dbDialect = DBDialect.find(databaseName);
   Query query = entityManager.createNativeQuery(dbDialect
      .getCurrentDateQuery());
   String valorData = (String) query.getSingleResult();
   SimpleDateFormat dateFormat = new SimpleDateFormat("dd/MM/yyyy HH:mm:ss");
   Date dataAtual = dateFormat.parse(valorData);

Notas

* Essa implementação é dependente do framework ORM, mas cada decisão que você toma deve ter prós que superem os contras segundo algum critério. Em um mundo ideal, deveríamos depender das abstrações e não das implementações. Em outras palavras, trata-se do “D” (Dependency inversion principle) do SOLID.

Referências

1. http://www.coderanch.com/t/622811/ORM/databases/createNativeQuery-JPA
2. http://openjpa.apache.org/builds/1.2.3/apache-openjpa/docs/jpa_overview_sqlquery_obj.html
3. http://stackoverflow.com/questions/6707115/get-hold-of-a-jdbc-connection-object-from-a-stateless-bean
4. http://stackoverflow.com/questions/20629523/how-to-know-database-type-programmatically-in-jpa
5. http://stackoverflow.com/questions/16994226/how-to-get-datasource-or-connection-from-jpa2-entitymanager-in-java-ee-6

  1. Nenhum comentário ainda.
  1. No trackbacks yet.

Deixe um comentário