पूरी जानकारी (और यह यहां वर्णित की तुलना में अधिक जटिल है और इस पर निर्भर हो सकती है कि Oracle ड्राइवरों का कौन सा विशेष संस्करण उपयोग में है) रिचर्ड यी के उत्तर में है - [अब नब्बल के लिए समाप्त लिंक]
नैबल से समाप्त होने से पहले त्वरित हड़पने...
रोजर, देखें:http://www.oracle.com/technetwork/database/enterprise-edition/jdbc-faq-090281.html#08_01
विशेष रूप से:साधारण डेटा प्रकार DATE और TIMESTAMP के साथ क्या हो रहा है? यह अनुभाग साधारण डेटा प्रकारों पर है। :-)
9.2 से पहले, Oracle JDBC ड्राइवरों ने DATE SQL प्रकार को java.sql.Timestamp में मैप किया था। यह एक निश्चित मात्रा में समझ में आता है क्योंकि Oracle DATE SQL प्रकार में दिनांक और समय दोनों की जानकारी होती है जैसा कि java.sql.Timestamp करता है। Java.sql.Date के लिए अधिक स्पष्ट मैपिंग कुछ समस्याग्रस्त थी क्योंकि java.sql.Date में समय की जानकारी शामिल नहीं है। यह भी मामला था कि RDBMS TIMESTAMP SQL प्रकार का समर्थन नहीं करता था, इसलिए DATE को टाइमस्टैम्प में मैप करने में कोई समस्या नहीं थी।
9.2 में TIMESTAMP समर्थन RDBMS में जोड़ा गया। DATE और TIMESTAMP के बीच का अंतर यह है कि TIMESTAMP में नैनोसेकंड शामिल हैं और DATE में नहीं है। इसलिए, 9.2 से शुरू होकर, DATE को दिनांक से मैप किया गया है और TIMESTAMP को टाइमस्टैम्प में मैप किया गया है। दुर्भाग्य से यदि आप समय की जानकारी रखने के लिए DATE के मानों पर भरोसा कर रहे थे, तो एक समस्या है।
इस समस्या के समाधान के कई तरीके हैं:
DATE के बजाय TIMESTAMP का उपयोग करने के लिए अपनी तालिकाएँ बदलें। यह शायद ही संभव है, लेकिन जब यह हो तो यह सबसे अच्छा समाधान है।
कॉलम को DATE के बजाय TIMESTAMP के रूप में परिभाषित करने के लिए परिभाषित कॉलम टाइप का उपयोग करने के लिए अपने एप्लिकेशन को बदलें। इसके साथ समस्याएं हैं क्योंकि आप वास्तव में परिभाषित कॉलम टाइप का उपयोग नहीं करना चाहते हैं जब तक आपको यह नहीं करना है (देखें परिभाषित कॉलम टाइप क्या है और मुझे इसका उपयोग कब करना चाहिए?)।
getObject के बजाय getTimestamp का उपयोग करने के लिए अपने एप्लिकेशन को बदलें। जब संभव हो तो यह एक अच्छा समाधान है, हालांकि कई अनुप्रयोगों में सामान्य कोड होता है जो getObject पर निर्भर करता है, इसलिए यह हमेशा संभव नहीं होता है।
V8संगत कनेक्शन गुण सेट करें। यह JDBC ड्राइवरों को नए के बजाय पुराने मैपिंग का उपयोग करने के लिए कहता है। आप इस ध्वज को कनेक्शन गुण या सिस्टम गुण के रूप में सेट कर सकते हैं। आप कनेक्शन गुण को java.util.Properties ऑब्जेक्ट में DriverManager.getConnection या OracleDataSource.setConnectionProperties को पास करके सेट करते हैं। आप अपने जावा कमांड लाइन में -D विकल्प को शामिल करके सिस्टम प्रॉपर्टी सेट करते हैं।
java -Doracle.jdbc.V8Compatible="true" MyAppOracle JDBC 11.1 इस समस्या को ठीक करता है। इस रिलीज़ के साथ ड्राइवर डिफ़ॉल्ट रूप से SQL DATE कॉलम को java.sql.Timestamp पर मैप करता है। सही मैपिंग प्राप्त करने के लिए V8Compatible को सेट करने की कोई आवश्यकता नहीं है। V8Compatible को दृढ़ता से बहिष्कृत किया गया है। आपको इसका इस्तेमाल बिल्कुल नहीं करना चाहिए। अगर आप इसे सही पर सेट करते हैं तो इससे कोई नुकसान नहीं होगा, लेकिन आपको इसका इस्तेमाल बंद कर देना चाहिए।
हालांकि इसका उपयोग शायद ही कभी इस तरह से किया गया था, V8Compatible का अस्तित्व दिनांक से दिनांक के मुद्दे को ठीक करने के लिए नहीं बल्कि 8i डेटाबेस के साथ संगतता का समर्थन करने के लिए था। 8i (और पुराने) डेटाबेस ने TIMESTAMP प्रकार का समर्थन नहीं किया। V8Compatible को सेट करने से न केवल डेटाबेस से पढ़ने पर SQL DATE को टाइमस्टैम्प में मैप किया जाता है, बल्कि डेटाबेस में लिखे जाने पर सभी टाइमस्टैम्प को SQL DATE में बदल दिया जाता है। चूंकि 8i समर्थित नहीं है, इसलिए 11.1 JDBC ड्राइवर इस संगतता मोड का समर्थन नहीं करते हैं। इस कारण से V8Compatible असमर्थित है।
जैसा कि ऊपर उल्लेख किया गया है, डेटाबेस से पढ़ते समय डिफ़ॉल्ट रूप से 11.1 ड्राइवर SQL DATE को टाइमस्टैम्प में परिवर्तित करते हैं। ऐसा करना हमेशा सही था और 9i में बदलाव एक गलती थी। 11.1 ड्राइवर सही व्यवहार पर वापस आ गए हैं। यहां तक कि अगर आपने अपने आवेदन में V8Compatible सेट नहीं किया है, तो भी आपको ज्यादातर मामलों में व्यवहार में कोई अंतर नहीं दिखना चाहिए। यदि आप DATE कॉलम को पढ़ने के लिए getObject का उपयोग करते हैं तो आपको अंतर दिखाई दे सकता है। परिणाम दिनांक के बजाय टाइमस्टैम्प होगा। चूंकि टाइमस्टैम्प दिनांक का उपवर्ग है, यह आम तौर पर कोई समस्या नहीं है। जहां आपको अंतर दिखाई दे सकता है, यदि आप समय घटक को कम करने के लिए DATE से दिनांक तक रूपांतरण पर भरोसा करते हैं या यदि आप मूल्य पर toString करते हैं। अन्यथा परिवर्तन पारदर्शी होना चाहिए।
अगर किसी कारण से आपका ऐप इस बदलाव के प्रति बहुत संवेदनशील है और आपके पास बस 9i-10g व्यवहार होना चाहिए, तो एक कनेक्शन प्रॉपर्टी है जिसे आप सेट कर सकते हैं। mapDateToTimestamp को गलत पर सेट करें और ड्राइवर डिफ़ॉल्ट 9i-10g व्यवहार पर वापस आ जाएगा और DATE से दिनांक तक मैप करेगा।
यदि संभव हो, तो आपको अपने कॉलम प्रकार को DATE के बजाय TIMESTAMP में बदलना चाहिए।
-रिचर्ड
रोजर वॉस ने लिखा:मैंने स्टैक ओवरफ्लो पर निम्नलिखित प्रश्न/समस्या पोस्ट की है, इसलिए यदि कोई संकल्प जानता है, तो इसका उत्तर वहां देखना अच्छा होगा:
जावा JDBC के माध्यम से iBATIS का उपयोग करके Oracle SQL DATE रूपांतरण समस्या
यहाँ समस्या का विवरण दिया गया है:
मैं वर्तमान में जावा से iBATIS का उपयोग करके Oracle sql DATE रूपांतरण समस्या से जूझ रहा हूं।
मैं Oracle JDBC पतले ड्राइवर ojdbc14 संस्करण 10.2.0.4.0 का उपयोग कर रहा हूँ। आईबीएटीआईएस संस्करण 2.3.2। जावा 1.6.0_10-rc2-b32.
समस्या DATE प्रकार के एक स्तंभ के इर्द-गिर्द घूमती है जिसे SQL के इस स्निपेट द्वारा लौटाया जा रहा है:
तालिका से चुनें
पैकेज प्रक्रिया कॉल एक रेफरी कर्सर देता है जिसे एक टेबल में लपेटा जा रहा है जहां परिणाम सेट को पढ़ना आसान है जैसे कि एक टेबल के खिलाफ एक चुनिंदा क्वेरी थी।
PL/SQL डेवलपर में, SQL DATE प्रकार के FROM_DATE को लौटाए गए स्तंभों में से एक में दिन के समय की सटीकता होती है:
Tue Dec 16 23:59:00 PST 2008
लेकिन जब मैं इसे iBATIS और JDBC के माध्यम से एक्सेस करता हूं, तो मान केवल दिन के लिए सटीक रहता है:
Tue Dec 16 12:00:00 AM PST 2008
इस तरह प्रदर्शित होने पर यह स्पष्ट होता है:
होना चाहिए था:1229500740000 मिलीसेकंड युग के बाद सेमंगलवार, दिसंबर 16, 2008 11:59:00 अपराह्न पीएसटी
लेकिन इसके बजाय इसे प्राप्त करना:1229414400000 मिलीसेकंड युग के बाद सेमंगलवार, 16 दिसंबर, 2008 12:00:00 पूर्वाह्न पीएसटी (कक्षा java.sql.Date के उदाहरण के रूप में)
कोई फर्क नहीं पड़ता कि मैं क्या कोशिश करता हूं, मैं जावा जेडीबीसी और आईबीएटीआईएस के माध्यम से लौटाए जाने वाले इस DATE कॉलम की पूरी सटीकता को उजागर करने में असमर्थ हूं।
iBATIS किससे मैपिंग कर रहा है:
FROM_DATE:2008-12-03:कक्षा java.sql.Date
वर्तमान iBATIS मैपिंग यह है:
मैंने भी कोशिश की है:
या
लेकिन सभी प्रयास किए गए मैपिंग एक ही छोटा दिनांक मान प्राप्त करते हैं। ऐसा लगता है कि JDBC ने iBATIS को छूने से पहले ही डेटा सटीकता को खोने का नुकसान किया है।
स्पष्ट रूप से मैं JDBC और iBATIS के माध्यम से अपनी कुछ डेटा सटीकता खो रहा हूं जो तब नहीं हो रहा है जब मैं PL/SQL डेवलपर में एक ही SQL स्निपेट को परीक्षण स्क्रिप्ट के रूप में चला रहा हूं। बिल्कुल भी स्वीकार्य नहीं, बहुत निराशाजनक, और अंततः बहुत डरावना।