java.util.Date बनाम java.sql.Date


जवाबों:


585

बधाई हो, आपने 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 के इस भाग से बचने देगा: पूरी तरह से।


17
अच्छा उत्तर। लेकिन क्या DBA के लिए थोड़ी सी भी लंबी अवधि के लिए तारीखों को संग्रहीत नहीं किया जाता है?
चेरोविम

26
शायद, हालांकि डीबीए: आम तौर पर अपनी आरडीबीएमएस पसंद के लिए जाते हैं और हर उस चीज़ को अस्वीकार करते हैं जो सीधे उस आरडीबीएमएस के बारे में नहीं है ( मैं आपको देख रहा हूं, ओरेकल प्रशंसक ) जबकि जावा अनुप्रयोगों से उन सभी के साथ काम करने की उम्मीद है। व्यक्तिगत रूप से मैं अपने तर्क को DB में रखना पसंद नहीं करता।
एस्को

2
मेरा mysql कॉलम एक डेटाटाइम है, लेकिन ps.setDate (नया java.sql.Date (myObject.getCreatedDate) ()। GetTime ()) कर रहा है; मैं मिलीसेकंड भाग को खो रहा हूं, इसे कैसे ठीक करूं?
ब्लेंकमैन

2
अपने मिलीसेकंड को न खोने के लिए: new java.sql.Timestamp (careDate.getTime ())
Kieveli

3
मैंने उल्लेख किया है कि यह एक सामान्य बग है जो कि विशिष्ट है, जबकि यह विनिर्देश द्वारा नहीं होना चाहिए।
एस्को जू

60

LATE EDIT: जावा 8 से शुरू होकर आपको java.util.Datejava.sql.Dateतो इसका उपयोग करना चाहिए और न ही यदि आप इससे बच सकते हैं, और इसके बजाय java.timeपैकेज (जोडा पर आधारित) का उपयोग करना चाहते हैं, बजाय इसके कि कुछ और। यदि आप जावा 8 पर नहीं हैं, तो यहां मूल प्रतिक्रिया है:


java.sql.Date- जब आप पुस्तकालयों के तरीकों / निर्माणकर्ताओं को बुलाते हैं जो इसका उपयोग करते हैं (जैसे कि JDBC)। अन्यथा नहीं। आप उन अनुप्रयोगों / मॉड्यूल के लिए डेटाबेस पुस्तकालयों पर निर्भरता का परिचय नहीं देना चाहते हैं जो जेडीबीसी के साथ स्पष्ट रूप से व्यवहार नहीं करते हैं।

java.util.Date- इसका उपयोग करने वाले पुस्तकालयों का उपयोग करते समय। अन्यथा, कई कारणों से जितना संभव हो उतना कम:

  • यह परिवर्तनशील है, जिसका अर्थ है कि आपको हर बार जब आप इसे पास करते हैं या किसी विधि से इसे वापस करते हैं तो इसकी एक रक्षात्मक प्रतिलिपि बनानी होगी।

  • यह बहुत अच्छी तरह से तारीखों को संभाल नहीं करता है, जो कि आपके जैसे लोगों को सही मायने में लगता है, सोचना चाहिए कि कक्षाओं को संभालना चाहिए।

  • अब, क्योंकि juD यह बहुत अच्छी तरह से काम नहीं करता है, इसलिए भयंकर रूप से Calendarकक्षाएं शुरू की गईं। वे भी आपस में मिलनसार और काम करने के लिए भयानक हैं, और यदि आपके पास कोई विकल्प नहीं है, तो इससे बचना चाहिए।

  • बेहतर विकल्प हैं, जैसे जोडा टाइम एपीआई ( जो शायद जावा 7 में भी बन सकता है और एपीआई को संभालने वाली नई आधिकारिक तारीख बन सकता है - एक त्वरित खोज कहती है कि यह नहीं होगा)।

अगर आपको लगता है कि जोडा जैसी नई निर्भरता का परिचय देना कठिन है long, तो वस्तुओं में टाइमस्टैम्प क्षेत्रों के लिए उपयोग करने के लिए यह सब बुरा नहीं है, हालांकि मैं खुद उन्हें आमतौर पर ज्यूडी में लपेटता हूं, जब वे चारों ओर से गुजरते हैं, प्रकार की सुरक्षा के लिए और प्रलेखन के रूप में।


5
डेटाबेस में भंडारण करते समय हमें java.time को java.sql पर क्यों पसंद करना चाहिए? मैं बयान में वास्तव में दिलचस्प हूं, लेकिन मैं यह समझना चाहता हूं कि क्यों :)
जीन-फ्रांस्वा सवार्ड 14

@ जीन-फ़्राँस्वास्वार्द मुझे आशा है कि आपने अपने प्रश्न का उत्तर पा लिया है क्योंकि आपने वह टिप्पणी पोस्ट की है - लेकिन यहाँ एक उत्तर है, पूर्णता के लिए: यह अभी भी पूरी तरह से ठीक है आदि के java.sql.Date साथ PreparedStatement! लेकिन जब आप इसे पास कर रहे होते हैं, तो एक का उपयोग करें LocalDateजिसे आप उपयोग करते समय java.sql.Date.valueOfऔर java.sql.Date.valueOfइसे सेट करते समय परिवर्तित करते हैं , और इसे जितनी जल्दी हो सके वापस बदल सकते हैं java.sql.Date.toLocalDate - फिर से, क्योंकि आप java.sql को जितना संभव हो उतना कम शामिल करना चाहते हैं, और क्योंकि यह पारस्परिक है।
gustafc

19

उपयोग करने का एकमात्र समय java.sql.Dateए में है PreparedStatement.setDate। अन्यथा, उपयोग करें java.util.Date। यह बता रहा है कि ResultSet.getDateरिटर्न मिलता है, java.sql.Dateलेकिन इसे सीधे सौंपा जा सकता है java.util.Date


3
Ehm, परिणाम # getDate () sql.Date (जो उपयोग बढ़ाता है) लौटाता है।
Esko

3
@ एस्को - "एहम", मैंने तय किया कि इससे पहले कि आप टिप्पणी करें (और डाउनवोट किए गए)।
पॉल टॉम्बलिन

1
यह नोट करना महत्वपूर्ण है कि कारण एक java.sql.Date को java.util को सौंपा जा सकता है। इसलिए, क्योंकि पहला दूसरे का उपवर्ग है।
dj18

2
ऐसा क्यों है कि यह बता रहा है कि जब पूर्व को बाद में विस्तारित किया java.sql.Dateजा सकता है, तो उसे सौंपा जा सकता है java.util.Date? वह बिंदु जो आप बनाने की कोशिश कर रहे हैं?
लेर्न

11

मेरे पास एक ही मुद्दा था, एक तैयार कथन में वर्तमान तिथि डालने का सबसे आसान तरीका यह है:

preparedStatement.setDate(1, new java.sql.Date(new java.util.Date().getTime()));

2
कैंट को इसके साथ टाइमजोन मिलता है।
एराणसिकोग्लू

4

tl; डॉ

न तो उपयोग करें।

java.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.OffsetDateTime

Instantjava.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.Date

java.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.time लाइब्रेरी की तालिका


1
कोरोना वायरस द्वारा प्लेग संदर्भ की जगह के लिए अपवोट। अब और अधिक भरोसेमंद।
एक्यूरानुरग 2

2

जावा में 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());
}

0

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यदि उनके कार्यान्वयन के विवरण से स्पष्ट किया जाता है।

हमारी साइट का प्रयोग करके, आप स्वीकार करते हैं कि आपने हमारी Cookie Policy और निजता नीति को पढ़ और समझा लिया है।
Licensed under cc by-sa 3.0 with attribution required.