sql >> データベース >  >> RDS >> Oracle

JavaJDBCを介したiBATISを使用したOracleSQLDATE変換の問題

    完全な情報(およびここで説明するよりも複雑で、使用しているOracleドライバーの特定のバージョンによって異なる場合があります)は、RichardYeeの回答にあります-[Nabbleへのリンクの有効期限が切れています]

    ナブルから期限切れになる前にすばやくつかむ...

    Roger、参照:http://www.oracle.com/technetwork/database/enterprise-edition/jdbc-faq-090281.html#08_01

    具体的には:単純なデータ型DATEとTIMESTAMPで何が起こっているのですか?このセクションでは、単純なデータ型について説明します。 :-)

    9.2より前のバージョンでは、OracleJDBCドライバーはDATESQLタイプをjava.sql.Timestampにマップしていました。 Oracle DATE SQLタイプには、java.sql.Timestampと同様に日付と時刻の両方の情報が含まれているため、これにはある程度の意味があります。 java.sql.Dateには時間情報が含まれていないため、java.sql.Dateへのより明白なマッピングには多少問題がありました。 RDBMSがTIMESTAMPSQLタイプをサポートしていない場合もあったため、DATEをTimestampにマッピングすることに問題はありませんでした。

    9.2では、TIMESTAMPサポートがRDBMSに追加されました。 DATEとTIMESTAMPの違いは、TIMESTAMPにはナノ秒が含まれ、DATEには含まれないことです。したがって、9.2以降、DATEはDateにマップされ、TIMESTAMPはTimestampにマップされます。残念ながら、時間情報を含めるためにDATE値に依存している場合は、問題があります。

    この問題に対処するには、いくつかの方法があります。

    DATEの代わりにTIMESTAMPを使用するようにテーブルを変更します。これが可能になることはおそらくめったにありませんが、可能であれば最善の解決策です。

    アプリケーションを変更して、defineColumnTypeを使用して、列をDATEではなくTIMESTAMPとして定義します。必要がない限りdefineColumnTypeを使用したくないため、これには問題があります(defineColumnTypeとは何ですか、いつ使用する必要がありますか?を参照してください)。

    getObjectではなくgetTimestampを使用するようにアプリケーションを変更します。これは可能な場合は優れたソリューションですが、多くのアプリケーションにはgetObjectに依存する汎用コードが含まれているため、常に可能であるとは限りません。

    V8Compatible接続プロパティを設定します。これにより、JDBCドライバーは、新しいマッピングではなく古いマッピングを使用するようになります。このフラグは、接続プロパティまたはシステムプロパティとして設定できます。接続プロパティを設定するには、DriverManager.getConnectionまたはOracleDataSource.setConnectionPropertiesに渡されるjava.util.Propertiesオブジェクトに追加します。システムプロパティを設定するには、Javaコマンドラインに-Dオプションを含めます。

    java -Doracle.jdbc.V8Compatible ="true" MyAppOracle JDBC 11.1は、この問題を修正します。このリリース以降、ドライバーはデフォルトでSQLDATE列をjava.sql.Timestampにマップします。正しいマッピングを取得するためにV8Compatibleを設定する必要はありません。 V8Compatibleは強く非推奨です。まったく使用しないでください。 trueに設定しても何も害はありませんが、使用を中止する必要があります。

    そのように使用されることはめったにありませんが、V8Compatibleは、DATE to Dateの問題を修正するためではなく、8iデータベースとの互換性をサポートするために存在していました。 8i(およびそれ以前)のデータベースは、TIMESTAMPタイプをサポートしていませんでした。 V8Compatibleを設定すると、データベースから読み取ったときにSQL DATEがタイムスタンプにマップされるだけでなく、データベースに書き込まれたときにすべてのタイムスタンプがSQLDATEに変換されました。 8iはサポートされていないため、11.1JDBCドライバーはこの互換モードをサポートしていません。このため、V8Compatibleはサポートされていません。

    上記のように、11.1ドライバーは、データベースから読み取るときに、デフォルトでSQLDATEをタイムスタンプに変換します。これは常に正しいことであり、9iでの変更は間違いでした。 11.1ドライバーは正しい動作に戻りました。アプリケーションでV8Compatibleを設定していなくても、ほとんどの場合、動作に違いは見られません。 getObjectを使用してDATE列を読み取ると、違いに気付く場合があります。結果は、日付ではなくタイムスタンプになります。 TimestampはDateのサブクラスであるため、これは通常問題にはなりません。違いに気付くかもしれないのは、DATEからDateへの変換に依存して時間コンポーネントを切り捨てた場合、または値に対してtoStringを実行した場合です。それ以外の場合、変更は透過的である必要があります。

    何らかの理由でアプリがこの変更に非常に敏感であり、単に9i-10gの動作が必要な場合は、設定できる接続プロパティがあります。 mapDateToTimestampをfalseに設定すると、ドライバーはデフォルトの9i-10gの動作に戻り、DATEをDateにマップします。

    可能であれば、列タイプをDATEではなくTIMESTAMPに変更する必要があります。

    -リチャード

    Roger Vossは次のように書いています:stackoverflowに次の質問/問題を投稿したので、誰かが解決策を知っているなら、そこで答えられるのを見るのは良いことです:

    JavaJDBCを介したiBATISを使用したOracleSQLDATE変換の問題

    問題の説明は次のとおりです:

    現在、JavaのiBATISを使用したOraclesqlDATE変換の問題に取り組んでいます。

    OracleJDBCシンドライバojdbc14バージョン10.2.0.4.0を使用しています。 iBATISバージョン2.3.2。 Java1.6.0_10-rc2-b32。

    この問題は、次のSQLスニペットによって返されるDATE型の列を中心に発生します。

    SELECT * FROM TABLE(pk_invoice_qry.get_contract_rate(?、?、?、?、?、?、?、?、?、?))from_dateによる注文

    パッケージプロシージャの呼び出しは、テーブルにラップされている参照カーソルを返します。このカーソルは、テーブルに対する選択クエリであるかのように、結果セットを簡単に読み取ることができます。

    PL / SQL Developerでは、返される列の1つであるSQL DATE型のFROM_DATEは、時刻に対する精度があります。

    Tue Dec 16 23:59:00 PST 2008
    

    しかし、iBATISとJDBCを介してこれにアクセスすると、値は今日まで精度を保持するだけです:

    Tue Dec 16 12:00:00 AM PST 2008
    

    このように表示すると、これはより明確になります:

    2008年12月16日11:59:00PMPST

    のepochTuesdayから1229500740000ミリ秒である必要があります。

    ただし、代わりにこれを取得します:2008年12月16日12:00:00 AM PST(クラスjava.sql.Dateのインスタンスとして)

    のepochTuesdayから1229414400000ミリ秒

    何を試しても、JavaJDBCとiBATISを介して返されるこのDATE列の完全な精度を公開することはできません。

    iBATISがマッピングしているのはこれです:

    FROM_DATE:2008-12-03:クラスjava.sql.Date

    現在のiBATISマッピングは次のとおりです:

    私も試しました:

    または

    ただし、試行されたすべてのマッピングは、同じ切り捨てられた日付値を生成します。まるで、iBATISがデータに触れる前に、JDBCがデータの精度を失うというダメージをすでに与えているかのようです。

    テストスクリプトと同じSQLスニペットを実行しているPL/SQL Developerにとどまっている場合は発生しない、JDBCとiBATISを使用することで、データの精度の一部が失われていることは明らかです。まったく受け入れられず、非常に苛立たしく、最終的には非常に恐ろしいです。



    1. バーカーの表記

    2. PostgreSQLの誤った並べ替え

    3. 安全な方法でSQLインジェクション攻撃を防ぐ方法

    4. MySQLレプリケーションセットアップのフェイルバック操作を実行する方法