2008-12-20 17 views
13

के माध्यम से आईबीएटीआईएस का उपयोग करते हुए ओरेकल एसक्यूएल तिथि रूपांतरण समस्या मैं वर्तमान में जावा से आईबीएटीआईएस का उपयोग कर ओरेकल एसक्यूएल दिनांक रूपांतरण समस्या के साथ कुश्ती कर रहा हूं।जावा जेडीबीसी

ओरेकल जेडीबीसी पतली चालक ojdbc14 संस्करण 10.2.0.4.0 का उपयोग कर रहा हूँ। iBATIS संस्करण 2.3.2। जावा 1.6.0_10-आरसी 2-बी 32।

समस्या

दिनांक प्रकार का एक स्तंभ है कि SQL के इस स्निपेट द्वारा दिया जा रहा है के आसपास घूमती है:

SELECT * 
FROM TABLE(pk_invoice_qry.get_contract_rate(?,?,?,?,?,?,?,?,?,?)) order by from_date 

पैकेज प्रक्रिया कॉल एक रेफरी कर्सर कि जहां के लिए एक टेबल में लिपटे की जा रही है देता है तो आसान है परिणाम सेट को पढ़ने के लिए जैसे कि किसी तालिका के विरुद्ध एक चुनिंदा क्वेरी थी।

PL/SQL डेवलपर में, स्तंभों में से एक लौटे, FROM_DATE एसक्यूएल दिनांक प्रकार की, दिन के समय के लिए सटीक है:

Tue Dec 16 23:59:00 PST 2008 

लेकिन जब मैं iBATIS और JDBC, मूल्य के माध्यम से इस का उपयोग केवल दिन के लिए सटीक को बरकरार रखे हुए:

Tue Dec 16 12:00:00 AM PST 2008 

यह स्पष्ट है जब इतनी तरह दिखाया गया है:

किया जाना चाहिए था:

012,351,
1229500740000 milliseconds since epoch 
Tuesday, December 16, 2008 11:59:00 PM PST 

लेकिन इस के बजाय हो रही:

1229414400000 milliseconds since epoch 
Tuesday, December 16, 2008 12:00:00 AM PST 
(as instance of class java.sql.Date) 

कोई फर्क नहीं पड़ता कि मैं क्या करने की कोशिश, मैं जावा JDBC और iBATIS के माध्यम से दिए जाने वाले इस तिथि स्तंभ से भरा परिशुद्धता का पर्दाफाश करने में असमर्थ हूँ।

FROM_DATE : 2008-12-03 : class java.sql.Date 

वर्तमान iBATIS मानचित्रण यह है::

यह क्या iBATIS से मानचित्रण है

<result property="from_date" jdbcType="DATE" javaType="java.sql.Date"/> 

मैं भी कोशिश की है:

<result property="from_date" jdbcType="DATETIME" javaType="java.sql.Date"/> 

या

<result property="from_date" jdbcType="TIMESTAMP" javaType="java.sql.Timestamp"/> 

लेकिन सभी प्रयास किए गए मैपिंग्स एक ही संक्षिप्त दिनांक मूल्य उत्पन्न करते हैं। ऐसा लगता है कि जेबीबीसी पहले से ही आईबीएटीआईएस को छूने से पहले डेटा परिशुद्धता खोने का नुकसान कर चुका है।

स्पष्ट रूप से मैं जेडीबीसी और आईबीएटीआईएस के माध्यम से जाकर अपने कुछ डेटा परिशुद्धता खो रहा हूं जो तब नहीं हो रहा है जब मैं पीएल/एसक्यूएल डेवलपर में एक परीक्षण स्क्रिप्ट के रूप में एक ही एसक्यूएल स्निपेट चला रहा हूं। बिल्कुल स्वीकार्य नहीं, बहुत निराशाजनक, और अंततः बहुत डरावना।

उत्तर

8

पूर्ण जानकारी (और यह और अधिक जटिल की तुलना में यहाँ वर्णित और पर जो ओरेकल चालकों के विशेष संस्करण के उपयोग में हैं निर्भर हो सकता है) रिचर्ड यी के answe में है यहाँ आर - [Nabble को अब समाप्त हो कड़ी]


त्वरित हड़पने से पहले यह nabble से समाप्त हो रहा है ...

रोजर, देखें: http://www.oracle.com/technetwork/database/enterprise-edition/jdbc-faq-090281.html#08_01

विशेष रूप से: सरल डेटा प्रकार क्या है DATE और TIMESTAMP के साथ चल रहा है? यह अनुभाग सरल डेटा प्रकारों पर है। :-)

9.2 से पहले, ओरेकल जेडीबीसी ड्राइवरों ने DATE SQL प्रकार को java.sql.Timestamp में मैप किया। इसने कुछ निश्चित ज्ञान दिया क्योंकि ओरेकल DATE एसक्यूएल प्रकार में java.sql.Timestamp जैसे दिनांक और समय की जानकारी दोनों होती है। Java.sql.Date के लिए अधिक स्पष्ट मानचित्रण java.sql.Date में कुछ हद तक समस्याग्रस्त था जिसमें समय की जानकारी शामिल नहीं है। यह भी मामला था कि आरडीबीएमएस ने टाइमस्टैम्प एसक्यूएल प्रकार का समर्थन नहीं किया था, इसलिए टाइममैप से DATE को मैपिंग करने में कोई समस्या नहीं थी।

9.2 में TIMESTAMP समर्थन आरडीबीएमएस में जोड़ा गया था। DATE और TIMESTAMP के बीच का अंतर यह है कि TIMESTAMP में नैनोसेकंड शामिल हैं और DATE नहीं है। इसलिए, 9.2 से शुरू होने पर, DATE को तारीख को मैप किया गया है और टाइमस्टैम्प को टाइमस्टैम्प में मैप किया गया है। दुर्भाग्यवश यदि आप समय की जानकारी रखने के लिए DATE मानों पर भरोसा कर रहे थे, तो एक समस्या है।

अपने टेबल, DATE के बजाय TIMESTAMP उपयोग करने के लिए बदलें:

इस समस्या का समाधान करने के कई तरीके हैं। यह शायद ही कभी संभव है, लेकिन यह सबसे अच्छा समाधान है जब यह है।

DATE को TIMESTAMP के रूप में कॉलम को परिभाषित करने के लिए DefineColumnType का उपयोग करने के लिए अपने एप्लिकेशन को बदलें। इसके साथ समस्याएं हैं क्योंकि आप वास्तव में defineColumnType का उपयोग नहीं करना चाहते हैं जब तक आपको यह देखना न पड़े (देखें कि DefineColumnType क्या है और मुझे इसका उपयोग कब करना चाहिए?)।

getObject के बजाय getTimestamp का उपयोग करने के लिए आप एप्लिकेशन को बदलें। जब संभव हो तो यह एक अच्छा समाधान है, हालांकि कई अनुप्रयोगों में जेनेरिक कोड होता है जो getObject पर निर्भर करता है, इसलिए यह हमेशा संभव नहीं होता है।

वी 8 संगत कनेक्शन संपत्ति सेट करें। यह जेडीबीसी ड्राइवरों को नए के बजाए पुराने मानचित्रण का उपयोग करने के लिए कहता है। आप इस ध्वज को कनेक्शन संपत्ति या सिस्टम प्रॉपर्टी के रूप में सेट कर सकते हैं। आप java.util.Properties ऑब्जेक्ट को DriverManager.getConnection या OracleDataSource.setConnectionProperties में पास करके कनेक्शन प्रॉपर्टी सेट करते हैं। आपने अपनी जावा कमांड लाइन में ए-डी विकल्प सहित सिस्टम प्रॉपर्टी सेट की है।

जावा-Doracle.jdbc.V8 संगत = "सत्य" MyApp ओरेकल जेडीबीसी 11.1 इस समस्या को हल करता है। इस रिलीज के साथ शुरुआत ड्राइवर डिफ़ॉल्ट रूप से java.sql.Timestamp पर SQL दिनांक कॉलम मानचित्र करता है। सही मैपिंग प्राप्त करने के लिए V8 संगत सेट करने की कोई आवश्यकता नहीं है। V8 संगत दृढ़ता से बहिष्कृत है। आपको इसका बिल्कुल उपयोग नहीं करना चाहिए। यदि आप इसे सत्य पर सेट करते हैं तो इससे कुछ भी नुकसान नहीं पहुंचाएगा, लेकिन आपको इसका उपयोग करना बंद कर देना चाहिए।

हालांकि इसका शायद ही कभी उपयोग किया जाता था, वी 8 कॉम्पैक्टेंट दिनांक से दिनांक बिंदु को ठीक करने के लिए नहीं बल्कि 8i डेटाबेस के साथ संगतता का समर्थन करने के लिए मौजूद था। 8i (और पुराने) डेटाबेस TIMESTAMP प्रकार का समर्थन नहीं करते थे। V8 संगत को सेट करने से डेटाबेस से पढ़ने पर SQL टाइम को टाइमस्टैम्प में मैप किया जा सकता है, यह डेटाबेस में लिखे जाने पर सभी टाइमस्टैम्प को SQL DATE में परिवर्तित करने का भी कारण बनता है। चूंकि 8i desupported है, 11.1 जेडीबीसी ड्राइवर इस संगतता मोड का समर्थन नहीं करते हैं। इस कारण से V8 संगत है desupported।

जैसा ऊपर बताया गया है, डेटाबेस से पढ़ने पर डिफ़ॉल्ट रूप से 11.1 ड्राइवर SQL टाइम को टाइमस्टैम्प में कनवर्ट करते हैं। यह हमेशा सही काम था और 9i में परिवर्तन एक गलती थी। 11.1 ड्राइवर सही व्यवहार में वापस आ गए हैं। यहां तक ​​कि यदि आपने अपने आवेदन में V8 संगत सेट नहीं किया है, तो आपको अधिकांश मामलों में व्यवहार में कोई अंतर नहीं दिखना चाहिए। यदि आप DATE कॉलम पढ़ने के लिए getObject का उपयोग करते हैं तो आप एक अंतर देख सकते हैं। परिणाम एक तिथि के बजाय एक टाइमस्टैम्प होगा। चूंकि टाइमस्टैम्प तिथि का उप-वर्ग है, यह आम तौर पर एक समस्या नहीं है। जहां आप एक अंतर देख सकते हैं, यदि आप समय से घटने के लिए रूपांतरण से भरोसा करते हैं या समय घटक को छोटा करने के लिए या यदि आप मूल्य पर स्ट्रिंग करते हैं। अन्यथा परिवर्तन पारदर्शी होना चाहिए।

यदि किसी कारण से आपका ऐप इस बदलाव से बहुत संवेदनशील है और आपके पास बस 9i-10g व्यवहार होना चाहिए, तो एक कनेक्शन प्रॉपर्टी सेट हो सकती है जिसे आप सेट कर सकते हैं। MapDateToTimestamp को गलत पर सेट करें और ड्राइवर डिफ़ॉल्ट 9i-10g व्यवहार पर वापस आ जाएगा और तिथि से DATE तक मानचित्र करेगा।

यदि संभव हो, तो आपको DATE के बजाय अपना कॉलम प्रकार TIMESTAMP में बदलना चाहिए।

-Richard


रोजर वॉस ने लिखा है: मैं, प्रश्न/stackoverflow पर समस्या निम्नलिखित तैनात इसलिए यदि किसी को भी एक प्रस्ताव जानता है, यह वहाँ जवाब को देखने के लिए अच्छा होगा:

Oracle SQL, DATE

मैं वर्तमान में WRES हूँ: जावा JDBC के माध्यम से iBATIS का उपयोग कर

यहाँ रूपांतरण समस्या समस्या विवरण दिया गया है जावा से iBATIS का उपयोग करते हुए ओरेकल एसक्यूएल दिनांक रूपांतरण समस्या के साथ टलिंग करें।

ओरेकल जेडीबीसी पतली चालक ojdbc14 संस्करण 10.2.0.4.0 का उपयोग कर रहा हूँ। iBATIS संस्करण 2.3.2। जावा 1.6.0_10-आरसी 2-बी 32।

समस्या दिनांक प्रकार का एक स्तंभ है कि SQL के इस स्निपेट द्वारा दिया जा रहा है के आसपास घूमती है:

चुनें * मेज से (pk_invoice_qry.get_contract_rate (,,,,,,?????? ,?,?,?)) from_date

पैकेज प्रक्रिया कॉल एक रेफरी कर्सर देता है जिसे एक तालिका में लपेटा जा रहा है, जहां परिणाम सेट को पढ़ने में आसान होता है, हालांकि तालिका के विरुद्ध एक चयन क्वेरी थी।

PL/SQL डेवलपर में, स्तंभों में से एक लौटे, FROM_DATE एसक्यूएल दिनांक प्रकार की, दिन के समय के लिए सटीक है:

Tue Dec 16 23:59:00 PST 2008 

लेकिन जब मैं iBATIS और JDBC, मूल्य के माध्यम से इस का उपयोग केवल दिन के लिए सटीक को बरकरार रखे हुए:

Tue Dec 16 12:00:00 AM PST 2008 

यह स्पष्ट है जब इतनी तरह दिखाया गया है:

चाहिए किया गया: युग 01 के बाद से 1229500740000 मिलीसेकेंडमंगलवार, दिसंबर 16, 2008 23:59:00 पीएसटी

लेकिन इस के बजाय हो रही: के बाद से 1229414400000 मिलीसेकेंड युग मंगलवार, दिसंबर 16, 2008 12:00:00 AM PST (कक्षा जावा के उदाहरण के रूप में। sql.Date)

कोई फर्क नहीं पड़ता कि मैं क्या प्रयास करता हूं, मैं जावा जेडीबीसी और आईबीएटीआईएस के माध्यम से वापस आने के लिए इस DATE कॉलम की पूरी परिशुद्धता का पर्दाफाश करने में असमर्थ हूं।

FROM_DATE: 2008/12/03: वर्ग java.sql

क्या iBATIS से मानचित्रण है यह है।

मैं भी कोशिश की है:: दिनांक

वर्तमान iBATIS मानचित्रण यह है

या

लेकिन सभी प्रयास किया मैपिंग ही उपज छोटा मूल्य दिनांक। ऐसा लगता है कि जेबीबीसी पहले ही आईबीएटीआईएस को छूने से पहले डेटा परिशुद्धता खोने का नुकसान कर चुका है।

स्पष्ट रूप से मैं जेडीबीसी और आईबीएटीआईएस के माध्यम से जाकर कुछ डेटा परिशुद्धता खो रहा हूं जो तब नहीं हो रहा है जब मैं पीएल/एसक्यूएल डेवलपर में एक परीक्षण स्क्रिप्ट के रूप में एक ही एसक्यूएल स्निपेट चला रहा हूं। बिल्कुल स्वीकार्य नहीं, बहुत निराशाजनक, और अंततः बहुत डरावना।

+0

लिंक अब और काम नहीं कर रहा है; ( –

+0

एक प्रतिलिपि मिली और इसे यहां जोड़ा गया ... –

+0

@Gwyn Evans आपके द्वारा दिए गए लिंक टूटे हुए हैं। उन्हें काम करने वाले लिंक के साथ अपडेट करें। – OO7

0

समस्या java.sql.Date का उपयोग है। Javadoc के मुताबिक, java.sql.Date उदाहरण द्वारा लिपटे मिलीसेकंड मानों को एसक्यूएल की परिभाषा के अनुरूप, विशेष समय क्षेत्र में घंटों, मिनट, सेकंड और मिलीसेकंड को शून्य पर सेट करके 'सामान्यीकृत' होना चाहिए। DATE

0

हां, मुझे लगता है - सादा एसक्यूएल दिनांक मानक केवल दिन संकल्प को स्टोर करना होगा।

ओरेकल, दोनों की तारीख और समय का समर्थन करता है अलग ढंग से यद्यपि SQL2 मानक से: दरअसल, यहां Oracle की दिनांक प्रकार पर एक टुकड़ा है। दो अलग-अलग इकाइयों, दिनांक और समय का उपयोग करने के बजाय, ओरेकल केवल एक, DATE का उपयोग करता है। दिनांक प्रकार एक विशेष आंतरिक प्रारूप में संग्रहीत है जिसमें केवल महीने, दिन और वर्ष शामिल नहीं है, बल्कि घंटे, मिनट और दूसरा शामिल है।

जो बिंदु बनाता है कि ओरेकल की तिथि मानक SQL DATE से अधिक है।

हम्म, ओरेकल पीएल/एसक्यूएल लोग मूल्यों को पकड़ने के लिए बड़े पैमाने पर DATE का उपयोग करते हैं जहां वे दूसरे के संकल्प पर निर्भर करते हैं। ऐसा लगता है कि iBATIS को हाइबरनेट एसक्यूएल डायलेक्ट अवधारणा की तरह कुछ चाहिए जहां java.sql.Date के माध्यम से DATE को व्याख्या करने की बजाय, ओवरराइड कर सकते हैं और इसके बजाय java.util.Date के माध्यम से व्याख्या कर सकते हैं, जिसे जावाडॉक्स मिलीसेकंद रिज़ॉल्यूशन की अनुमति के रूप में परिभाषित करता है।

दुर्भाग्य से जब मैं की तरह कुछ करने के लिए मानचित्रण बदल दिया है:

<result property="from_date" jdbcType="DATE" javaType="java.util.Date"/> 

या

<result property="from_date" jdbcType="DATETIME" javaType="java.util.Date"/> 

यह अभी भी है प्रतीत होता है पहले एक java.sql.Date के लिए एसक्यूएल, DATE अनुवाद किया है और समय खो दिया है दिन परिशुद्धता का।

5

मुझे पता चला कि इस समस्या को कैसे हल किया जाए। iBATIS कस्टम प्रकार हैंडलर पंजीकृत होने की अनुमति देता है। तो मेरी sqlmap-config.xml फ़ाइल में मैं इस कहा:

<typeAlias alias="OracleDateHandler" type="com.tideworks.ms.CustomDateHandler"/> 
<typeHandler callback="OracleDateHandler" jdbcType="DATETIME" javaType="date"/> 

और फिर इस वर्ग जो iBATIS TypeHandlerCallback इंटरफ़ेस लागू करता है कहा:

// corrected getResult()/setParameter() to correctly deal with when value is null 
public class CustomDateHandler implements TypeHandlerCallback { 
    @Override 
    public Object getResult(ResultGetter getter) throws SQLException { 
     final Object obj = getter.getTimestamp(); 
     return obj != null ? (Date) obj : null; 
    } 

    @Override 
    public void setParameter(ParameterSetter setter,Object value) throws SQLException { 
     setter.setTimestamp(value != null ? new Timestamp(((Date)value).getTime()) : null); 
    } 

    @Override 
    public Object valueOf(String datetime) { 
     return Timestamp.valueOf(datetime); 
    } 
} 

Whennever मैं एक Oracle, DATE अब मैं वर्णन मैप करने की आवश्यकता यह इतना की तरह:

<result property="from_date" jdbcType="DATETIME" javaType="date"/> 
+0

अच्छा, मुझे यकीन नहीं था कि इस मुद्दे को कैसे दूर किया जाए, लेकिन मुझे खुशी है कि मैं आपको सही दिशा में इंगित कर सकता हूं – ninesided

+0

मैं आपके आयात नहीं देख सकता। जब आप किसी तारीख को मान कास्टिंग कर रहे हैं, तो क्या वह उपयोग या एसक्यूएल है? – bwfrieds

2

मैं jdbcType = "TIMESTAMP" के बदले jdbcType = "दिनांक"

• समस्या मेरी समस्या हल कर दिया है:

• हल:

सादर।

पेड्रो

+0

<परिणाम स्तंभ = "FECHA_HORA_UTC_POSICION" संपत्ति = "fechaHoraUtcPosicion" jdbcType = "date" /> <परिणाम स्तंभ = "FECHA_HORA_UTC_POSICION" संपत्ति = "fechaHoraUtcPosicion" में भेजा पाया jdbcType = "TIMESTAMP" /> –

+1

TIMESTAMP के साथ आपके परिणामों की सफलता को चालू करता है आप ओरेकल जेडीबीसी ड्राइवर के किस संस्करण से निपट रहे हैं, इस पर निर्भर हैं। उन्होंने अपनी नीति को बदलकर पीएल के पूर्ण मिलीसेकंद परिशुद्धता का अनुवाद कैसे किया है/SQL दिनांक प्रकार java.util.Date प्रकार। – RogerV

+0

यह मेरे लिए काम करता है Ojdbc14 10.2.0.4.0 के साथ बैटिस 3.0.5 (शायद नए प्रकार के हैंडलरों की वजह से) – fglez

1

समस्या ओरेकल चालक के साथ है। #column_name करने के लिए तिथि #:

सबसे अच्छा समाधान मैंने पाया सब jdbcType = jdbcType = "TIMESTAMP" को "DATE" और सभी #column_name बदलने के लिए था TIMESTAMP #

तो बदलने के लिए:

<result property="from_date" jdbcType="DATE" javaType="java.sql.Date"/> 

को
<result property="from_date" jdbcType="TIMESTAMP" javaType="java.sql.Date"/> 
0

रिचर्ड यी कि Oracle की नवीनतम ड्राइवर समस्या को ठीक उल्लेख है। मैं इसकी पुष्टि कर सकता हूं। यहां 10.2 ड्राइवरों के साथ एक ही समस्या थी, आज ojdbc5.jar (11.2.0.1.0) में अपग्रेड किया गया, और समस्या अब खत्म हो गई है।

संबंधित मुद्दे