java.util.Dateबनाम java.sql.Date: कब और क्यों उपयोग करें?
java.util.Dateबनाम java.sql.Date: कब और क्यों उपयोग करें?
जवाबों:
बधाई हो, आपने JDBC: डेट क्लास हैंडलिंग के साथ मेरे पसंदीदा पालतू जानवर को मारा है।
मूल रूप से डेटाबेस आमतौर पर डेटाइम क्षेत्रों के कम से कम तीन रूपों का समर्थन करते हैं जो तिथि, समय और टाइमस्टैम्प हैं। इनमें से प्रत्येक की JDBC में एक समान श्रेणी है और उनमें से प्रत्येक का विस्तार हैjava.util.Date । इन तीनों में से प्रत्येक के त्वरित शब्दार्थ निम्नलिखित हैं:
java.sql.DateSQL DATE से मेल खाती है जिसका अर्थ है कि यह साल, महीने और दिनों को संग्रहीत करता है जबकि घंटे, मिनट, सेकंड और मिलीसेकंड को अनदेखा किया जाता है। इसके अतिरिक्त sql.Dateटाइमजोन से बंधा नहीं है।java.sql.TimeSQL TIME से मेल खाती है और जैसा कि स्पष्ट होना चाहिए, केवल घंटे, मिनट, सेकंड और मिलीसेकंड के बारे में जानकारी शामिल है ।java.sql.TimestampSQL TIMESTAMP से मेल खाती है, जो नैनोसेकंड के लिए सटीक तिथि है ( ध्यान दें कि util.Dateकेवल अनुकूलन योग्य परिशुद्धता के साथ मिलीसेकंड का समर्थन करता है! )।इन तीन प्रकारों के संबंध में JDBC ड्राइवरों का उपयोग करते समय सबसे आम बग्स में से एक यह है कि प्रकारों को गलत तरीके से संभाला जाता है। इसका मतलब यह है कि sql.Dateयह समय क्षेत्र विशिष्ट है, sql.Timeइसमें वर्तमान वर्ष, महीना और दिन वगैरह वगैरह शामिल हैं।
क्षेत्र के SQL प्रकार पर निर्भर करता है, वास्तव में। PreparedStatementतीनों मूल्यों के लिए बसने वाला है, #setDate()एक है sql.Date, के #setTime()लिए sql.Timeऔर के #setTimestamp()लिए sql.Timestamp।
ध्यान दें कि यदि आप उपयोग ps.setObject(fieldIndex, utilDateObject);करते हैं तो आप वास्तव में util.Dateअधिकांश JDBC ड्राइवरों को एक सामान्य दे सकते हैं जो खुशी से इसे खाएंगे जैसे कि यह सही प्रकार का था लेकिन जब आप डेटा का अनुरोध करते हैं, तो आप नोटिस कर सकते हैं कि आप वास्तव में सामान गायब कर रहे हैं।
मैं जो कह रहा हूं कि मिलीसेकंड / नैनोसेकंड को सादे लंबे समय के रूप में सहेजें और उन्हें उन वस्तुओं में परिवर्तित करें जो आप उपयोग कर रहे हैं ( अनिवार्य जोडा-टाइम प्लग )। एक हैकी तरीका जो किया जा सकता है वह है तारीख घटक को एक लंबे और समय के घटक के रूप में दूसरे के रूप में संग्रहीत करना, उदाहरण के लिए अभी 20100221 और 154536123 होगा। इन मैजिक नंबरों का उपयोग SQL प्रश्नों में किया जा सकता है और डेटाबेस से दूसरे में पोर्टेबल होगा। आपको JDBC / Java Date API के इस भाग से बचने देगा: पूरी तरह से।
LATE EDIT: जावा 8 से शुरू होकर आपको java.util.Dateन java.sql.Dateतो इसका उपयोग करना चाहिए और न ही यदि आप इससे बच सकते हैं, और इसके बजाय java.timeपैकेज (जोडा पर आधारित) का उपयोग करना चाहते हैं, बजाय इसके कि कुछ और। यदि आप जावा 8 पर नहीं हैं, तो यहां मूल प्रतिक्रिया है:
java.sql.Date- जब आप पुस्तकालयों के तरीकों / निर्माणकर्ताओं को बुलाते हैं जो इसका उपयोग करते हैं (जैसे कि JDBC)। अन्यथा नहीं। आप उन अनुप्रयोगों / मॉड्यूल के लिए डेटाबेस पुस्तकालयों पर निर्भरता का परिचय नहीं देना चाहते हैं जो जेडीबीसी के साथ स्पष्ट रूप से व्यवहार नहीं करते हैं।
java.util.Date- इसका उपयोग करने वाले पुस्तकालयों का उपयोग करते समय। अन्यथा, कई कारणों से जितना संभव हो उतना कम:
यह परिवर्तनशील है, जिसका अर्थ है कि आपको हर बार जब आप इसे पास करते हैं या किसी विधि से इसे वापस करते हैं तो इसकी एक रक्षात्मक प्रतिलिपि बनानी होगी।
यह बहुत अच्छी तरह से तारीखों को संभाल नहीं करता है, जो कि आपके जैसे लोगों को सही मायने में लगता है, सोचना चाहिए कि कक्षाओं को संभालना चाहिए।
अब, क्योंकि juD यह बहुत अच्छी तरह से काम नहीं करता है, इसलिए भयंकर रूप से Calendarकक्षाएं शुरू की गईं। वे भी आपस में मिलनसार और काम करने के लिए भयानक हैं, और यदि आपके पास कोई विकल्प नहीं है, तो इससे बचना चाहिए।
बेहतर विकल्प हैं, जैसे जोडा टाइम एपीआई ( जो शायद जावा 7 में भी बन सकता है और एपीआई को संभालने वाली नई आधिकारिक तारीख बन सकता है - एक त्वरित खोज कहती है कि यह नहीं होगा)।
अगर आपको लगता है कि जोडा जैसी नई निर्भरता का परिचय देना कठिन है long, तो वस्तुओं में टाइमस्टैम्प क्षेत्रों के लिए उपयोग करने के लिए यह सब बुरा नहीं है, हालांकि मैं खुद उन्हें आमतौर पर ज्यूडी में लपेटता हूं, जब वे चारों ओर से गुजरते हैं, प्रकार की सुरक्षा के लिए और प्रलेखन के रूप में।
java.sql.Date साथ PreparedStatement! लेकिन जब आप इसे पास कर रहे होते हैं, तो एक का उपयोग करें LocalDateजिसे आप उपयोग करते समय java.sql.Date.valueOfऔर java.sql.Date.valueOfइसे सेट करते समय परिवर्तित करते हैं , और इसे जितनी जल्दी हो सके वापस बदल सकते हैं java.sql.Date.toLocalDate - फिर से, क्योंकि आप java.sql को जितना संभव हो उतना कम शामिल करना चाहते हैं, और क्योंकि यह पारस्परिक है।
उपयोग करने का एकमात्र समय java.sql.Dateए में है PreparedStatement.setDate। अन्यथा, उपयोग करें java.util.Date। यह बता रहा है कि ResultSet.getDateरिटर्न मिलता है, java.sql.Dateलेकिन इसे सीधे सौंपा जा सकता है java.util.Date।
java.sql.Dateजा सकता है, तो उसे सौंपा जा सकता है java.util.Date? वह बिंदु जो आप बनाने की कोशिश कर रहे हैं?
मेरे पास एक ही मुद्दा था, एक तैयार कथन में वर्तमान तिथि डालने का सबसे आसान तरीका यह है:
preparedStatement.setDate(1, new java.sql.Date(new java.util.Date().getTime()));
न तो उपयोग करें।
java.time.Instant की जगह java.util.Datejava.time.LocalDate की जगह java.sql.Datejava.util.Date बनाम java.sql.Date: कब और क्यों उपयोग करना है?
ये दोनों वर्ग डिजाइन और कार्यान्वयन में भयानक, त्रुटिपूर्ण हैं। प्लेग कोरोनावायरस की तरह बचें ।
इसके बजाय java.time कक्षाओं का उपयोग करें , जिसे जेएसआर 310 में परिभाषित किया गया है। ये कक्षाएं डेट-टाइम हैंडलिंग के साथ काम करने के लिए एक उद्योग की अग्रणी रूपरेखा हैं। ये प्रतिस्थापित पूरी तरह खूनी भयंकर विरासत वर्गों जैसे Date, Calendar, SimpleDateFormat, और इस तरह।
java.util.Dateपहला, java.util.Dateयूटीसी में एक पल का प्रतिनिधित्व करने के लिए है, जिसका अर्थ है शून्य घंटे-मिनट-सेकंड के यूटीसी से ऑफसेट।
java.time.Instantअब इसकी जगह java.time.Instant।
Instant instant = Instant.now() ; // Capture the current moment as seen in UTC.
java.time.OffsetDateTimeInstantjava.time का मूल भवन-ब्लॉक वर्ग है । अधिक लचीलेपन के लिए, एक ही उद्देश्य के लिए OffsetDateTimeसेट का उपयोग करें ZoneOffset.UTC: UTC में एक पल का प्रतिनिधित्व करना।
OffsetDateTime odt = OffsetDateTime.now( ZoneOffset.UTC ) ;
आप इस ऑब्जेक्ट को JDBC 4.2 के PreparedStatement::setObjectसाथ या बाद में किसी डेटाबेस में भेज सकते हैं ।
myPreparedStatement.setObject( … , odt ) ;
प्राप्त करें।
OffsetDateTime odt = myResultSet.getObject( … , OffsetDateTime.class ) ;
java.sql.Datejava.sql.Dateवर्ग भी भयानक और अप्रचलित है।
यह वर्ग केवल एक तिथि का प्रतिनिधित्व करने के लिए है, बिना समय के दिन और समय क्षेत्र के बिना। दुर्भाग्य से, एक डिजाइन की भयानक हैक में, यह वर्ग विरासत में मिला है java.util.Dateजिसमें से एक क्षण (UTC में समय के साथ एक तारीख) का प्रतिनिधित्व करता है। इसलिए यह वर्ग केवल तारीख का नाटक कर रहा है, जबकि वास्तव में यूटीसी के समय और निहित ऑफसेट को ले जा रहा है। यह बहुत भ्रम का कारण बनता है। इस वर्ग का उपयोग कभी न करें।
java.time.LocalDateइसके बजाय, java.time.LocalDateकिसी भी समय-दिन या किसी भी समय क्षेत्र या ऑफसेट के बिना सिर्फ एक तारीख (वर्ष, माह, दिन-महीने) को ट्रैक करने के लिए उपयोग करें।
ZoneId z = ZoneId.of( "Africa/Tunis" ) ;
LocalDate ld = LocalDate.now( z ) ; // Capture the current date as seen in the wall-clock time used by the people of a particular region (a time zone).
डेटाबेस को भेजें।
myPreparedStatement.setObject( … , ld ) ;
प्राप्त करें।
LocalDate ld = myResultSet.getObject( … , LocalDate.class ) ;
Java.time ढांचे जावा 8 और बाद में बनाया गया है। इन कक्षाओं परेशानी वर्ष प्रतिस्थापित विरासत जैसे तिथि-समय कक्षाएं java.util.Date, Calendar, और SimpleDateFormat।
अधिक जानने के लिए, Oracle ट्यूटोरियल देखें । और कई उदाहरणों और स्पष्टीकरणों के लिए ढेर अतिप्रवाह खोजें। विशिष्टता JSR 310 है ।
Joda समय परियोजना, अब में रखरखाव मोड , प्रवास करने की सलाह देता java.time कक्षाएं।
आप अपने डेटाबेस से सीधे java.time वस्तुओं का आदान-प्रदान कर सकते हैं । JDBC 4.2 या उसके बाद के JDBC ड्राइवर का अनुपालन करें । तार की कोई जरूरत नहीं, कोई जरूरत नहींjava.sql.* कक्षाओं ।
Java.time कक्षाएं कहाँ से प्राप्त करें?
जावा में java.util.Date क्लास समय में एक विशेष क्षण (जैसे, .g।, 2013 Nov 25 16:30:45 से मिलीसेकंड तक) का प्रतिनिधित्व करता है, लेकिन DB में DATE डेटा प्रकार केवल दिनांक का प्रतिनिधित्व करता है (जैसे, 2013 नवंबर 25)। आपको गलती से DB को java.util.Date ऑब्जेक्ट प्रदान करने से रोकने के लिए, Java आपको SQL पैरामीटर को java.util.Date पर सेट करने की अनुमति नहीं देता है: सीधे
PreparedStatement st = ...
java.util.Date d = ...
st.setDate(1, d); //will not work
लेकिन यह अभी भी आपको यह करने की अनुमति देता है कि बल / इरादा (तब घंटे और मिनटों को डीबी चालक द्वारा अनदेखा किया जाएगा)। यह java.sql.Date वर्ग के साथ किया जाता है:
PreparedStatement st = ...
java.util.Date d = ...
st.setDate(1, new java.sql.Date(d.getTime())); //will work
एक java.sql.Date ऑब्जेक्ट समय में एक पल को स्टोर कर सकता है (ताकि java.util.Date से निर्माण करना आसान हो), लेकिन यदि आप इसे घंटे के लिए पूछने की कोशिश करते हैं तो एक अपवाद फेंक देंगे (एक होने की अपनी अवधारणा को लागू करने के लिए। केवल तारीख)। डीबी ड्राइवर को इस वर्ग को पहचानने और घंटे के लिए 0 का उपयोग करने की उम्मीद है। इसे इस्तेमाल करे:
public static void main(String[] args) {
java.util.Date d1 = new java.util.Date(12345);//ms since 1970 Jan 1 midnight
java.sql.Date d2 = new java.sql.Date(12345);
System.out.println(d1.getHours());
System.out.println(d2.getHours());
}
java.util.Dateमिलीसेकंड परिशुद्धता के साथ समय में एक विशिष्ट तत्काल का प्रतिनिधित्व करता है। यह समय-सीमा के बिना तारीख और समय की जानकारी दोनों का प्रतिनिधित्व करता है। Java.util.Date क्लास सेक्शनिबल, क्लोन करने योग्य और तुलनात्मक इंटरफ़ेस लागू करता है। यह विरासत में मिला है java.sql.Date, java.sql.Timeऔर java.sql.Timestampइंटरफेस।
java.sql.Datejava.util.Date क्लास का विस्तार करता है, जो समय की जानकारी के बिना तारीख का प्रतिनिधित्व करता है और इसका उपयोग केवल डेटाबेस के साथ काम करते समय किया जाना चाहिए। SQL DATE की परिभाषा के अनुरूप, किसी java.sql.Dateविशेष समय क्षेत्र में शून्य, मिनट, सेकंड, और मिलीसेकंड को शून्य पर सेट करके मिलीसेकंड मानों को 'सामान्यीकृत' किया जाना चाहिए, जिसके साथ आवृत्ति संबद्ध है।
यह के सभी सार्वजनिक तरीकों विरासत java.util.Dateजैसे getHours(), getMinutes(), getSeconds(), setHours(), setMinutes(), setSeconds()। जैसा java.sql.Dateकि समय की जानकारी को संग्रहीत नहीं करता है, यह सभी समय के संचालन को ओवरराइड करता है java.util.Dateऔर इन सभी तरीकों को फेंक देता है java.lang.IllegalArgumentExceptionयदि उनके कार्यान्वयन के विवरण से स्पष्ट किया जाता है।