Problema de data e hora com Hibernate e Oracle 8i

6 respostas
P

Olá Pessoal,
Sei que existe um forum do proprio Hibernate, mas tenho certeza que o pessoal que acessa o GUJ tem muito mais conhecimento que o pessoal do forum do hibernate.
O meu problema é um velho conhecido, mas acho que peguei uma combinação mais perigosa.
Estou tentando mapear um campo do tipo DATE no Oracle 8i. O Oracle 8i, para quem não conhece, ainda não possuia o tipo TIMESTAMP.
Bom, quero mapear este campo para um objeto da classe java.util.Date ou java.sql.Date
O problema propriamente dito é o seguinte. Se faço o mapping com o tipo date (type=“date”). O meu objeto Date só é preenchido com a data, o hibernate ignora a parte da hora.
Se utilizo (type=“time”) o hibernate pega somente a hora e ignora a data. Se utilizar o tipo timestamp obtenho uma Excecao (timestamp expected form column tal…; claro, pois ela não é do tipo timestamp).
Parece que este problema existe na versão 9i, mas a solução apresentada era ignorar o tipo no mapeamento. Ou seja, não mencionar o tipo e deixar o hibernate escolher pra você. Mas no 8i não funciona. Ignorar o tipo faz o hibernate escolher como tipo o timestamp, gerando a excecao timestamp expected for column …
Acho que devo fazer um tipo definido pelo usuário, mas acho um absurdo não haver nenhum tipo no hibernate capaz de resolver esse problema.
Se algum colega já passou esse aperto e conseguiu resolvê-lo de forma fácil e elegante, por favor, peço que compartilhe esta informação com outro colega de Java.

Agradeço a atençao dos colegas

6 Respostas

Dieval_Guizelini

Por curiosidade,

qua a versão do driver do oracle que você está utilizando? e a conexão é thin?

fw

Ps: apenas como uma idéia, você já tentou usar cast ou obter do banco como float?

P

O versão do driver que estou usando é a 10g e a conexão é do tipo thin. Tentei usar o driver 9i, embora não fiz todos os testes possíveis com este driver.
Cast eu ja tentei e não funciona. Não tentei como float. Só poderei fazer o teste na quarta-feira. Mas acho que é possivel que eu obtenha uma resposta do tipo “expected number for column” Mas vou tentar.
Você acha que o driver ou o tipo de conexão esteja influenciando o trantamento do objeto por parte do hibernate ?

Dieval_Guizelini

Olha,

certeza eu não tenho, mas o driver que estou utilizando em uma aplicação legada e que me dá bastante dor de cabeça é o driver do 9i para o jsdk 1.4:

Manifest-Version: 1.0 Specification-Title: "Oracle JDBC driver classes for use with JDK1.4" Specification-Version: "Oracle JDBC Driver version - 9.0.2.0.0" Specification-Vendor: "Oracle Corporation" . Implementation-Title: "ojdbc14.jar" Implementation-Version: "Oracle JDBC Driver version - 9.0.2.0.0" Implementation-Vendor: "Oracle Corporation" Implementation-Time: "Tue Apr 6 01:10:57 2004"

Acho que você pode tentar mudar o dialeto do hibernate de [org.hibernate.dialect.Oracle9Dialect] para [org.hibernate.dialect.OracleDialect] e se o jar [ojdbc14.jar] não resolver, dá para usar a versão mais antiga [classes12.jar].

Se isso não resolver, então terá que apelar, como sugestão:

Para saber se o problema está no hibernate ou no driver, faça uma conexão jdbc e busca com uma query simples e teste as possibilidade de conversão. Faça testes do tipo:
java.util.Date data =new java.util.Date( rs.getObject(coluna) );
java.util.Date data = new SimpleDateFormat("MM/dd/yy").parse( rs.getString(coluna)  );
java.util.Date data =new java.util.Date( 
   ((long)(rs.getFloat(coluna)*86400*1000))
   );

O número mágico é obtido do fato do oracle manter a data como um float, em que a parte inteira é o número de diase a fracionária a parte de um dia. Eu multipliquei por 1000 porque em java é em milisegundos e nõ em segundos.

Lembrando que a data no java é o tempo decorrido desde de 01/01/1970 0 horas (GMT).
Neste caso você pode ainda usar essa função em Oracle:

CREATE OR REPLACE FUNCTION DateLongForJava (
DATE_1 IN DATE) RETURN NUMBER IS

NDATE_1   NUMBER;
NDATE_2   NUMBER;
NSECOND_1 NUMBER(5,0);
NSECOND_2 NUMBER(5,0);

BEGIN
  -- Get Julian date number from first date (DATE_1)
  NDATE_1 := TO_NUMBER(TO_CHAR(DATE_1, 'J'));

  -- Get Julian date number from second date (DATE_2)
  NDATE_2 := TO_NUMBER(TO_CHAR(to_date('1900-01-01 0:0:0','yyyy-mm-dd hh24:mi:ss'), 'J'));

  -- Get seconds since midnight from first date (DATE_1)
  NSECOND_1 := TO_NUMBER(TO_CHAR(DATE_1, 'SSSSS'));

  -- Get seconds since midnight from second date (DATE_2)
  NSECOND_2 := TO_NUMBER(TO_CHAR(to_date('1900-01-01 0:0:0','yyyy-mm-dd hh24:mi:ss'), 'SSSSS'));

  RETURN (((NDATE_2 - NDATE_1) * 86400)+(NSECOND_2 - NSECOND_1))*1000;
END time_diff;

O problema é que você terá que usar query nativa para usá-las na recuperação destes valores.

Além dessas possibilidades, existe uma versão do driver da oracle para depuração, senão me engano com o sufixo _g no arquivo jar, que poderá te dar uma dica tb.

boa sorte, problemas com datas são sempre trabalhosos....

fw

P

Valeu pelas dicas. Acho que iiso abre novas possibilidades.
Vou começara testar.

Obrigado

Akila

Cara tenho que agradecer quem postou esse Tópico. Eu estava com um problema muito estranho com o oracle8i e algumas colunas do tipo varchar2.

Deixa eu conta que isso pode ajudar alguem.

Eu inseria um registro e tudo ok, nada de errado.
Quando eu atualizava o registro, somente a coluna que vinha antes da coluna do tipo DATE, tinha os 3 primeiros caracteres embaralhados. fiz o teste com todas as tabelas do meu bando e a mesma situação ocorria.

Então quando li isso que o oracle8i não em timestamp, resolvi remover a anotação temporal=timestamp nas entidades e o erro parou de ocorrer. Algum coisa muito estranha para min… mas é isso. só remover o tempora = timestamp que o problema acaba.

valeu.

C

Boa tarde

Faz tempo que esse tópico foi aberto mas estou tendo esse problema agora, pessoal estou com um problema parecido com os mencionados acima, no hibernate tenho um atributo do tipo Date onde irei armazenar data/hora, o oracle 8i não tem o tipo de dados timestamp que seria o ideal para essa situação, ele possui o tipo date.

Quando o hibernate faz o insert na base de dados esta gravando datas inválidas, ele esta truncando os valores de datas.

Bom eu estou utilizando o driver ojdbc14 e o dialeto org.hibernate.dialect.OracleDialect, já tentei utilizar as anotações @Temporal, tentei tirar essas anotações, mas mesmo assim não funcionou, será que alguém tem uma solução para esse tipo de problema ??

Valeu.

Criado 3 de fevereiro de 2008
Ultima resposta 5 de fev. de 2010
Respostas 6
Participantes 4