Oracle SQL DATE de conversion de problème à l'aide d'iBATIS via Java JDBC
Je suis actuellement à la lutte avec un Oracle SQL DATE de conversion de problème à l'aide d'iBATIS à partir de Java.
Suis à l'aide de l'Oracle JDBC mince pilote ojdbc14 version 10.2.0.4.0. iBATIS version 2.3.2. Java 1.6.0_10-rc2-b32.
Le problème tourne autour d'une colonne de type DATE qui est retourné par cet extrait de SQL:
SELECT *
FROM TABLE(pk_invoice_qry.get_contract_rate(?,?,?,?,?,?,?,?,?,?)) order by from_date
Le paquet d'appel de procédure retourne un ref cursor qui est enveloppé dans un TABLEAU où est alors facile de lire le résultat en tant que bien que ont été d'une requête select sur une table.
En PL/SQL Developer, l'une des colonnes retournées, FROM_DATE, de SQL de type DATE, a précision le moment de la journée:
Tue Dec 16 23:59:00 PST 2008
Mais quand j'y accéder via iBATIS et JDBC, la valeur ne conserve plus de précision à jour:
Tue Dec 16 12:00:00 AM PST 2008
C'est plus clair quand elle est affichée comme suit:
:
1229500740000 milliseconds since epoch
Tuesday, December 16, 2008 11:59:00 PM PST
Mais faire ceci à la place:
1229414400000 milliseconds since epoch
Tuesday, December 16, 2008 12:00:00 AM PST
(as instance of class java.sql.Date)
Peu importe ce que je tente, je suis incapable d'exposer toute la précision de cette colonne de DATE à être renvoyés via Java JDBC et iBATIS.
Ce iBATIS est cartographie de l'est: est-ce
FROM_DATE : 2008-12-03 : class java.sql.Date
L'actuel iBATIS de cartographie est ce:
<result property="from_date" jdbcType="DATE" javaType="java.sql.Date"/>
J'ai aussi essayé:
<result property="from_date" jdbcType="DATETIME" javaType="java.sql.Date"/>
ou
<result property="from_date" jdbcType="TIMESTAMP" javaType="java.sql.Timestamp"/>
Mais toutes les tentatives d'mappages de donner le même tronquée Date de valeur. C'est comme si JDBC a déjà fait le dommage de perdre de la précision des données avant de iBATIS même touche.
Est clair que je vais perdre un peu de ma précision des données via JDBC et iBATIS qui ne se produit pas quand je reste en PL/SQL Developer exécutent le même code SQL comme un script de test. Pas du tout acceptable, très frustrant, et, finalement, très effrayant.
OriginalL'auteur RogerV | 2008-12-20
Vous devez vous connecter pour publier un commentaire.
Le plein d'infos (et c'est plus complexe que celle décrite ici, et peut dépendre notamment de la version de l'Oracle pilotes sont en cours d'utilisation) est en Richard Yee réponse ici - [expiré lien vers Nabble]
Rapides à prendre avant l'expiration de nabble...
Roger,
Voir: http://www.oracle.com/technetwork/database/enterprise-edition/jdbc-faq-090281.html#08_01
Spécifiquement:
Types De Données Simples
Ce qui se passe avec la DATE et l'HORODATAGE?
Cette section est sur les types de données simples. 🙂
Avant 9.2, l'Oracle JDBC drivers cartographié la DATE SQL de type java.sql.Timestamp. Cela fait un certain nombre de sens, car l'Oracle DATE de type SQL contient à la fois la date et l'heure de l'information en tant que java.sql.Timestamp. Le plus évident de la cartographie pour java.sql.La Date a été quelque peu problématique que java.sql.Date de ne pas inclure l'information en temps. C'était également le cas des SGBD ne supporte pas le TIMESTAMP SQL, donc il n'y a pas de problème avec la cartographie de la DATE d'Horodatage.
En 9.2 HORODATAGE de soutien a été ajouté pour le SGBDR. La différence entre la DATE et l'HORODATAGE est que TIMESTAMP comprend nanosecondes et la DATE ne fonctionne pas. Ainsi, commencer à 9.2, la DATE est mappé à la Date et l'HORODATAGE est mappé à l'Horodatage. Malheureusement, si vous avez été en s'appuyant sur les valeurs de DATE en contiennent de l'information en temps, il y a un problème.
Il y a plusieurs façons d'aborder ce problème:
Modifier vos tables à l'utilisation d'HORODATAGE à la place de la DATE. C'est probablement rarement possible, mais c'est la meilleure solution quand il est.
Modifier votre application pour utiliser defineColumnType pour définir les colonnes TIMESTAMP plutôt que de DATE. Il y a des problèmes avec cela, parce que vous ne voulez vraiment pas à utiliser defineColumnType, sauf si vous avez (voir qu'est-Ce que defineColumnType et quand dois-je l'utiliser?).
Modifier votre application pour utiliser la méthode gettimestamp plutôt que getObject. C'est une bonne solution quand c'est possible, cependant, de nombreuses applications contiennent le code générique qui s'appuie sur la fonction getObject, de sorte qu'il n'est pas toujours possible.
Définir la V8Compatible propriété de la connexion. Cela dit les pilotes JDBC à utiliser l'ancienne cartographie plutôt que de le nouveau. Vous pouvez définir cet indicateur soit comme une propriété de la connexion ou d'un système de propriété. Vous définissez la propriété de connexion en l'ajoutant à la java.util.Propriétés de l'objet passé en DriverManager.getConnection ou à OracleDataSource.setConnectionProperties. Vous définissez le système de la propriété par l'inclusion d'une option-D dans votre ligne de commande java.
java -Doracle.jdbc.V8Compatible="true" MyApp
Oracle JDBC 11.1 résout ce problème. Début avec cette version, le pilote des cartes SQL colonnes de DATE pour java.sql.Horodatage par défaut. Il n'est pas nécessaire de définir V8Compatible pour obtenir la bonne cartographie. V8Compatible est fortement déconseillé. Vous ne devriez pas l'utiliser du tout. Si vous n'attribuez la valeur true, il ne fera pas de mal en soit, mais vous devez cesser de l'utiliser.
Bien qu'il a été rarement utilisé de cette façon, V8Compatible existait pas à fixer la DATE à la Date de la question, mais pour assurer la compatibilité avec 8i bases de données. 8i (et plus) les bases de données n'ont pas en charge le type TIMESTAMP. Réglage V8Compatible pas seulement causé SQL DATE à mapper à un Horodatage lors de la lecture de la base de données, il a également provoqué de tous les Timestamps être converti en SQL DATE écrite à la base de données. Depuis 8i est desupported, l'11.1 pilotes JDBC ne prennent pas en charge ce mode de compatibilité. Pour cette raison V8Compatible est desupported.
Comme mentionné ci-dessus, l'11.1 pilotes par défaut convertir SQL DATE d'Horodatage lors de la lecture à partir de la base de données. Cela a toujours été la bonne chose à faire et le changement dans 9i était une erreur. L'11.1 les conducteurs ont repris le comportement correct. Même si vous n'avez pas défini de V8Compatible dans votre application, vous ne devriez pas voir une différence dans le comportement, dans la plupart des cas. Vous pouvez remarquer une différence si vous utilisez la fonction getObject pour lire une colonne de DATE. Le résultat sera un Timestamp plutôt qu'une Date. Depuis le Timestamp est une sous-classe de la Date ce n'est généralement pas un problème. Lorsque vous remarquerez peut-être une différence est que si vous vous basez sur la conversion de DATE à DATE à tronquer le temps composant ou si vous ne toString sur la valeur. Sinon, le changement doit être transparent.
Si, pour quelque raison que votre application est très sensible à ce changement, et vous devez simplement avoir la 9i-10g de comportement, il est une propriété de la connexion que vous pouvez définir. Ensemble mapDateToTimestamp à false et que le pilote va revenir à la valeur par défaut 9i-10g comportement et la carte de DATE à DATE.
Si possible, vous devriez changer votre colonne de type TIMESTAMP à la place de la DATE.
-Richard
Roger Voss a écrit:
J'ai posté suite à la question/problème sur stackoverflow, donc si quelqu'un sait d'une résolution, ce serait bien de voir qu'il a répondu:
Oracle SQL DATE de conversion de problème à l'aide d'iBATIS via Java JDBC
Voici la description du problème:
Je suis actuellement à la lutte avec un Oracle sql DATE de conversion de problème à l'aide d'iBATIS à partir de Java.
Suis à l'aide de l'Oracle JDBC mince pilote ojdbc14 version 10.2.0.4.0. iBATIS version 2.3.2. Java 1.6.0_10-rc2-b32.
Le problème tourne autour d'une colonne de type DATE qui est retourné par cet extrait de SQL:
SELECT *
À PARTIR de la TABLE(pk_invoice_qry.get_contract_rate(?,?,?,?,?,?,?,?,?,?)) commande par from_date
Le paquet d'appel de procédure retourne un ref cursor qui est enveloppé dans un TABLEAU où est alors facile de lire le résultat en tant que bien que ont été d'une requête select sur une table.
En PL/SQL Developer, l'une des colonnes retournées, FROM_DATE, de SQL de type DATE, a précision le moment de la journée:
Mais quand j'y accéder via iBATIS et JDBC, la valeur ne conserve plus de précision à jour:
C'est plus clair quand elle est affichée comme suit:
:
1229500740000 millisecondes écoulées depuis l'époque
Mardi, décembre 16, 2008 11:59:00 PM PST
Mais faire ceci à la place:
1229414400000 millisecondes écoulées depuis l'époque
Mardi, décembre 16, 2008 12:00:00 PST
(comme instance de la classe java.sql.Date)
Peu importe ce que je tente, je suis incapable d'exposer toute la précision de cette colonne de DATE à être renvoyés via Java JDBC et iBATIS.
Ce iBATIS est cartographie de l'est: est-ce
FROM_DATE : 2008-12-03 : la classe java.sql.Date
L'actuel iBATIS de cartographie est ce:
J'ai aussi essayé:
ou
Mais toutes les tentatives d'mappages de donner le même tronquée Date de valeur. C'est comme si JDBC a déjà fait le dommage de perdre de la précision des données avant de iBATIS même touche.
Clairement, je suis de perdre certains de mes la précision des données via JDBC et iBATIS qui ne se produit pas quand je reste en PL/SQL Developer exécutent le même code SQL comme un script de test. Pas du tout acceptable, très frustrant, et, finalement, très effrayant.
A trouvé une copie et de l'ajouter ici...
Evans Les liens u ont donné de réponse sont cassés. Mise à jour avec les liens de travail.
Nabble on est parti (mais le texte est dans la réponse) mais j'ai trouvé le nouvel emplacement de la FAQ, il visés...
OriginalL'auteur Gwyn Evans
J'ai trouvé comment résoudre ce problème. iBATIS permis de type personnalisé gestionnaires afin d'être enregistré. Donc, dans mon sqlmap-config.xml fichier que j'ai ajouté ceci:
Et ensuite ajouté cette classe qui implémente l'iBATIS TypeHandlerCallback interface:
Whennever j'ai besoin de la carte Oracle DATE, j'ai maintenant le décrire comme suit:
Je ne peux pas voir vos importations. Lorsque vous êtes casting de la valeur à une Date, c'est que util ou sql?
OriginalL'auteur RogerV
J'ai résolu mon problème en utilisant jdbcType="TIMESTAMP" au lieu de jdbcType="DATE"
• PROBLÈME:
•RÉSOLU:
Ce qui concerne.
Pedro
S'avère que la réussite de vos résultats avec HORODATAGE dépendent de la version d'Oracle JDBC driver, vous avez affaire. Ils ne cessaient de changer leur politique quant à la façon de traduire l'intégralité précision à la milliseconde du PL/SQL de type DATE en java.util.Type de Date.
Il a travaillé pour MyBatis 3.0.5 avec ojdbc14 10.2.0.4.0 (probablement en raison de nouveaux gestionnaires de type)
OriginalL'auteur
Le problème est avec le Pilote Oracle.
La meilleure solution que j'ai trouvé était de changer tous les jdbcType="DATE" pour jdbcType="TIMESTAMP"
et tous les #column_name:DATE# de #column_name:TIMESTAMP#
Donc changer:
à
OriginalL'auteur bob
Le problème est l'utilisation de
java.sql.Date
. Selon le Javadoc, de l'ordre de la milliseconde valeurs enveloppé par unjava.sql.Date
instance doit être 'normalisé' les heures, les minutes, les secondes et les millisecondes à zéro dans le fuseau horaire particulier avec lequel l'instance est associée, afin de se conformer à la définition de SQLDATE
.OriginalL'auteur ninesided
Oui, je vois la plaine SQL DATE standard doit être seulement de stocker à jour de la résolution. En effet, voici un extrait sur Oracle DATE, type:
Qui en fait le point d'Oracle DATE dépasse la norme SQL DATE.
Hmm, Oracle PL/SQL gens utilisent DATE largement à conserver des valeurs où ils dépendent de la résolution de la deuxième. Ressemble iBATIS besoin de quelque chose comme Hibernate dialecte sql concept où, au lieu de l'interprétation de la DATE via java.sql.Date, pouvait passer outre et au lieu d'interpréter via java.util.Date, qui Javadocs définit comme autorisant la milliseconde.
Malheureusement, quand j'ai changé la cartographie à quelque chose comme:
ou
C'est encore apparemment d'abord traduit le SQL DATE en java.sql.La Date et la perte de temps de la journée de précision.
OriginalL'auteur RogerV
Richard Yee mentionne que Oracle pilotes les plus récents corriger le problème. Je peux le confirmer. Eu le même problème ici avec 10.2 pilotes, mis à jour aujourd'hui à ojdbc5.jar (11.2.0.1.0), et le problème a disparu.
OriginalL'auteur wallenborn