2010-10-25 7 views
14

के साथ दिनांक मुझे मिलीसेकंड के साथ तिथियों के प्रबंधन के बारे में कोई समस्या है। मैं दुकान मिलीसेकेंड के लिए TIMESTAMP उपयोग करने के लिए आवश्यकता को समझते हैं:java.sql.Timestamp का उपयोग वास्तविक java.util के रूप में कैसे करें। जेपीए

@Temporal(TIMESTAMP) 
@Column(name="DATE_COLUMN", nullable = false) 
@Override public java.util.Date getDate() { return this.date; } 

लेकिन अगर मैं java.util.Date का एक और उदाहरण के लिए इस तिथि तुलना नहीं कर सकते, जब तक कि मैं ध्यान बराबरी के आदेश करने के लिए (भुगतान) कॉल , क्योंकि this.date उदाहरण एक java.sql.Timestamp है। जेपीए से java.util.Date कैसे प्राप्त करें? क्योंकि जेपीए से आने वाली तारीख, भले ही विधि हस्ताक्षर java.util.Date वास्तव में java.sql.Timestamp का एक उदाहरण है।

java.util.Date newDate = new Date(this.date.getTime()); 
this.date.equals(newDate) == false 
newDate.equals(this.date) == true 

मैं दृढ़ता कक्षा में मेरी विधि को संशोधित करने की कोशिश कर दिया है:

@Override 
public Date getDate() { 
    return this.date == null ? null : new Date(this.date.getTime()); 
} 

यह काम कर रहा है, लेकिन यह डेटा के बहुत सारे के साथ कुशल नहीं है।

  • मैं अपने हठ वर्ग के डिजाइन को संशोधित कर सकता है, क्रम में persited तारीख से एक java.util.Date बनाने के लिए के बाद मैं इसे पुनः प्राप्त @PostLoad का उपयोग कर:

    अन्य विकल्प हैं।

  • मुझे आश्चर्य है कि मुझे ClassTransformer का उपयोग करके कोई परिणाम नहीं मिल सकता है?

क्या आपने कभी इस समस्या का सामना किया है? मैं सही ढंग से क्या नहीं करता? इस समस्या को संभालने का सबसे अच्छा तरीका क्या है?

+0

मुझे इस समस्या का बहुत बुरा संस्करण था जहां यह स्प्रिंग सिक्योरिटी की नमक तुलना खराब हो गई। स्पष्ट रूप से नमक के लिए एक sql.timestamp दिनांक संस्करण का उपयोग करने से उपयोग करने से भिन्न परिणाम मिलता है। दिनांक – Marc

उत्तर

7

java.sql.TimestampcompareTo(Date) विधि ओवरराइड करता है, तो यह compareTo(..)

का उपयोग कर संक्षेप में कोई समस्या नहीं होनी चाहिए - java.util.Date और java.sql.Timestamp परस्पर तुलना के योग्य हैं।

इसके अलावा, आप वस्तुओं की बजाय हमेशा date.getTime() की तुलना कर सकते हैं।

और इससे भी आगे - आप तारीख को संग्रहीत करने के लिए long फ़ील्ड का उपयोग कर सकते हैं। या यहां तक ​​कि DateTime (जोडा-टाइम से)

+0

दृढ़ता से आने वाली तारीख का उपयोग किसी अन्य ढांचे द्वारा किया जाता है जिसे संशोधित नहीं किया जा सकता है (बहुत सारे काम)। – chepseskaf

+0

मुझे अभी भी समस्या नहीं है .. – Bozho

+0

क्योंकि मैं तुलना प्रक्रिया को संशोधित नहीं कर सकता, मुझे मुख्य प्रणाली में java.util.Date प्रदान करने की आवश्यकता है। मैं जानना चाहता हूं कि तारीख को प्रभावी रूप से कैसे परिवर्तित किया जाए? – chepseskaf

4

मेरे अनुभव में आप java.sql.Timestamp को अपने तर्क में नहीं चाहते हैं - यह आपके द्वारा इंगित की गई बहुत सारी अजीब त्रुटियों को बनाता है, और यह नहीं करता है यदि आपका एप्लिकेशन धारावाहिकता करता है तो बेहतर हो जाएं।

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

संपादित करें: मुझे लगता है कि आप हाइबरनेट का उपयोग कर रहे हैं। आप एनोटेशन का उपयोग करते हैं आप कर सकते हैं:

@Type(type = "org.joda.time.contrib.hibernate.PersistentDateTime") 
public DateTime getProvisionByTime() { 
    return provisionByTime; 
} 

तो फिर आप अपने लगातार वस्तुओं में Jodatime से अच्छा दिनांक समय वस्तुओं मिल जाएगा।आप केवल एक तारीख करना चाहते हैं, तो आप इस तरह LOCALDATE उपयोग कर सकते हैं:

@Type(type = "org.joda.time.contrib.hibernate.PersistentLocalDate") 
public LocalDate getCloudExpireDate() { 
    return cloudExpireDate; 
} 

यदि आप Maven का उपयोग करें, निम्न निर्भरता मिलना चाहिए इस (आप हाइबरनेट संस्करणों अपडेट करनी पड़ सकती)

आप के लिए निर्धारित
<dependency> 
     <groupId>org.hibernate</groupId> 
     <artifactId>hibernate</artifactId> 
     <version>3.2.6.ga</version> 
    </dependency> 
    <dependency> 
     <groupId>org.hibernate</groupId> 
     <artifactId>hibernate-annotations</artifactId> 
     <version>3.3.1.GA</version> 
    </dependency> 

    <dependency> 
     <groupId>joda-time</groupId> 
     <artifactId>joda-time-hibernate</artifactId> 
     <version>1.2</version> 
    </dependency> 
    <dependency> 
     <groupId>joda-time</groupId> 
     <artifactId>joda-time</artifactId> 
      <version>1.6.1</version> 
    </dependency> 
+0

निश्चित रूप से, java.sql.Timestamp जेपीए द्वारा लगाया गया है। काश मैं बिना कर सकता था, लेकिन मैपिंग जेपीए द्वारा प्रदान की जाती है ... – chepseskaf

+0

जैसा कि आप हाइबरनेट का उपयोग कर रहे हैं, मुझे लगता है कि आप ऊपर दिए गए समाधान का प्रयास कर सकते हैं। – Knubo

+0

मैं परीक्षण करने की कोशिश करूंगा, लेकिन इस समाधान के साथ मैं पूर्ण जेपीए अनुपालन नहीं करूँगा ... – chepseskaf

1

जेपीए को java.util.Date की विशेषता के लिए java.util.Date वापस करना चाहिए, @Temporal (TIMESTAMP) एनोटेशन केवल दिनांक को संग्रहीत करने के तरीके को प्रभावित करना चाहिए। आपको java.sql.Timestamp वापस नहीं मिलना चाहिए।

आप किस जेपीए प्रदाता का उपयोग कर रहे हैं? क्या आपने EclipseLink, जेपीए संदर्भ कार्यान्वयन में यह कोशिश की है?

+0

हाइबरनेट मेरा जेपीए प्रदाता है;) – chepseskaf

12

टीबीएच, मुझे इसकी सटीक स्थिति का यकीन नहीं है, लेकिन वास्तव में Hibernate (जो आपका जेपीए प्रदाता है, है ना?) के साथ समस्या हो सकती है TIMESTAMP कॉलम संभालती है।

एक java.util.Date करने के लिए एक एसक्यूएल TIMESTAMP नक्शा करने के लिए, हाइबरनेट TimestampType जो वास्तव में अपने java.util.Date विशेषता के लिए एक java.sql.Timestamp प्रदान करेंगे उपयोग करता है। और जब यह "कानूनी" है, तो समस्या यह है कि Timestamp.equals(Object)सममित (पृथ्वी पर क्यों ?!) है और यह Date.equals(Object) के अर्थशास्त्र को तोड़ देता है।

परिणामस्वरूप, आप myDate.equals(someRealJavaUtilDate) का उपयोग नहीं कर सकते हैं, यदि myDate को SQL TIMESTAMP पर मैप किया गया है, जो वास्तव में स्वीकार्य नहीं है।

लेकिन हालांकि इस पर व्यापक रूप से हाइबरनेट मंचों पर चर्चा की गई है, उदाहरण के लिए this thread और this one (सभी पृष्ठों को पढ़ें), ऐसा लगता है कि हाइबरनेट उपयोगकर्ता और डेवलपर समस्या पर कभी सहमत नहीं थे (HB-681 जैसे मुद्दों को देखें) और मुझे समझ में नहीं आता क्यों।

शायद यह सिर्फ मुझे है, शायद मुझे दूसरों के लिए कुछ आसान याद आ रहा है, लेकिन समस्या मुझे स्पष्ट दिखती है और जब मैं अपराधी होने के लिए यह बेवकूफ java.sql.Timestamp मानता हूं, तब भी मुझे लगता है कि हाइबरनेट को इस मुद्दे से उपयोगकर्ताओं को ढालना चाहिए। मुझे समझ में नहीं आता क्यों गेविन इस पर सहमत नहीं थे।

मेरा सुझाव इस मुद्दे का प्रदर्शन करने वाला एक परीक्षण केस बनाना होगा (बहुत सरल होना चाहिए) और समस्या (फिर से) की रिपोर्ट करने के लिए यह देखने के लिए कि क्या आपको वर्तमान टीम से अधिक सकारात्मक प्रतिक्रिया मिलती है या नहीं।

इस बीच, आप एक कस्टम प्रकार इस्तेमाल कर सकते हैं कुछ इस तरह (मंच से लिया और चिपकाया है के रूप में) का उपयोग कर समस्या अपने आप को "ठीक" करने के लिए,:

public class TimeMillisType extends org.hibernate.type.TimestampType { 

    public Date get(ResultSet rs, String name) throws SQLException { 
     Timestamp timestamp = rs.getTimestamp(name); 
     if (timestamp == null) return null; 
     return 
      new Date(timestamp.getTime()+timestamp.getNanos()/1000000); 
    } 

} 
+1

यह पागल है। जैसा कि आपने मुझे सलाह दी है, मैं फिर से हाइबरनेट को शामिल करने की कोशिश करूंगा। – chepseskaf

+0

मैंने एक नया मुद्दा बनाया क्योंकि मैं अपने आवेदन में एक ही समस्या में चलाता हूं: https://hibernate.onjira.com/browse/HHH-6873 – Martin

2

समस्या डीएओ परीक्षण के लिए महत्वपूर्ण है:

Employer employer1 = new Employer(); 
employer1.setName("namenamenamenamenamename"); 
employer1.setRegistered(new Date(1111111111)); // <- Date field 

entityManager.persist(employer1); 
assertNotNull(employer1.getId()); 

entityManager.flush(); 
entityManager.clear(); 

Employer employer2 = entityManager.find(Employer.class, employer1.getId()); 
assertNotNull(employer2); 
assertEquals(employer1, employer2); // <- works 
assertEquals(employer2, employer1); // <- fails !!! 

तो परिणाम वास्तव में आश्चर्यजनक है और लेखन परीक्षण मुश्किल हो गए हैं।

लेकिन असली व्यापार तर्क में आप कभी भी सेट/मैप कुंजी के रूप में इकाई का उपयोग नहीं करेंगे क्योंकि यह बहुत बड़ा है और यह उत्परिवर्तनीय है। और आप समय मूल्यों की तुलना equal तुलना से कभी नहीं करेंगे। और पूरी संस्थाओं की तुलना करना भी टालना चाहिए।

सामान्य परिदृश्य मानचित्र/सेट कुंजी के लिए अपरिवर्तनीय इकाई आईडी का उपयोग करता है और compareTo() विधि के साथ समय मानों की तुलना करता है या बस getTime() मानों का उपयोग करता है।

लेकिन परीक्षण कर रही एक दर्द है तो मैं अपने ही लागू किया प्रकार संचालकों

http://pastebin.com/7TgtEd3x

http://pastebin.com/DMrxzUEV

और मैं बोली अधिरोहित है मैं का उपयोग करें:

package xxx; 

import org.hibernate.dialect.HSQLDialect; 
import org.hibernate.type.AdaptedImmutableType; 
import xxx.DateTimestampType; 

import java.util.Date; 

public class CustomHSQLDialect extends HSQLDialect { 

    public CustomHSQLDialect() { 
     addTypeOverride(DateTimestampType.INSTANCE); 
     addTypeOverride(new AdaptedImmutableType<Date>(DateTimestampType.INSTANCE)); 
    } 
} 

मैं हेवन ' टी अभी तक तय नहीं है - क्या मैं परीक्षण और उत्पादन या केवल परीक्षणों के लिए इस दृष्टिकोण का उपयोग करता हूं।

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