JPA और हाइबरनेट के साथ UTC टाइम ज़ोन में दिनांक / समय और टाइमस्टैम्प कैसे स्टोर करें


106

UTC (GMT) टाइम ज़ोन के रूप में डेटाबेस में दिनांक / समय संग्रहीत करने के लिए मैं JPA / Hibernate को कैसे कॉन्फ़िगर कर सकता हूं? इस एनोटेट JPA इकाई पर विचार करें:

public class Event {
    @Id
    public int id;

    @Temporal(TemporalType.TIMESTAMP)
    public java.util.Date date;
}

यदि दिनांक 2008-फरवरी-03 9:30 बजे प्रशांत मानक समय (पीएसटी) है, तो मुझे डेटाबेस में संग्रहीत 2008-फरवरी-03 5:30 बजे का यूटीसी समय चाहिए। इसी तरह, जब तारीख डेटाबेस से पुनर्प्राप्त की जाती है, तो मैं चाहता हूं कि इसे यूटीसी के रूप में व्याख्या किया जाए। तो इस मामले में 530pm Upm यूटीसी है। जब यह प्रदर्शित होता है तो इसे 9:30 बजे पीएसटी के रूप में स्वरूपित किया जाएगा।


1
व्लाद मिहालसी का जवाब एक अद्यतन उत्तर प्रदान करता है (हाइबरनेट 5.2+ के लिए)
दीनी

जवाबों:


73

हाइबरनेट 5.2 के साथ, अब आप निम्न कॉन्फ़िगरेशन संपत्ति का उपयोग करके UTC समय क्षेत्र को बाध्य कर सकते हैं:

<property name="hibernate.jdbc.time_zone" value="UTC"/>

अधिक जानकारी के लिए, इस लेख को देखें


19
मैंने लिखा है कि एक भी: डी नाउ, लगता है कि हाइबरनेट में इस सुविधा के लिए समर्थन किसने जोड़ा?
व्लाद मिहालसी

ओह, अभी-अभी मुझे पता चला है कि नाम और चित्र आपकी प्रोफ़ाइल और उन लेखों में समान हैं ... अच्छा काम व्लाद :)
दीनी

@VladMihalcea अगर यह मैसकल के लिए है, तो किसी useTimezone=trueको कनेक्शन स्ट्रिंग में उपयोग करके MySql को टाइमज़ोन का उपयोग करने की आवश्यकता है । तब केवल प्रॉपर्टी सेट hibernate.jdbc.time_zoneकरना काम करेगा
TheCoder

वास्तव में, आपको useLegacyDatetimeCodeझूठ
बोलने की

2
PostgreSQL के साथ प्रयोग किए जाने पर hibernate.jdbc.time_zone को नजरअंदाज किया जाता है या इसका कोई असर नहीं होता है
एलेक्स आर

48

मेरे ज्ञान का सबसे अच्छा करने के लिए, आपको अपना संपूर्ण जावा ऐप यूटीसी टाइमज़ोन में डालना होगा (ताकि हाइबरनेट यूटीसी में तारीखों को स्टोर करेगा), और आपको सामान प्रदर्शित करते समय वांछित जो भी टाइमज़ोन बदलने की आवश्यकता होगी (कम से कम हम इसे करते हैं) इस तरफ)।

स्टार्टअप पर, हम करते हैं:

TimeZone.setDefault(TimeZone.getTimeZone("Etc/UTC"));

और DateFormat को वांछित टाइमज़ोन सेट करें:

fmt.setTimeZone(TimeZone.getTimeZone("Europe/Budapest"))

5
mitchnull, आपका समाधान सभी मामलों में काम नहीं करेगा क्योंकि Hibernate प्रतिनिधि JDBC ड्राइवर को दिनांक निर्धारित करता है और प्रत्येक JDBC ड्राइवर दिनांक और समय क्षेत्रों को अलग-अलग तरीके से हैंडल करता है। stackoverflow.com/questions/4123534/… देखें ।
डेरेक महार

2
लेकिन अगर मैं अपना ऐप JVM को सूचित करना शुरू करता हूं "-Duser.timezone = + 00: 00" संपत्ति, क्या समान व्यवहार नहीं है?
rafa.ferreira

8
जहां तक ​​मैं बता सकता हूं, यह सभी मामलों में काम करेगा जब जेवीएम और डेटाबेस सर्वर अलग-अलग समय क्षेत्रों में हैं।
शेन

stevekuo और @mitchnull divestoclimb हल देखने के जो नीचे कहीं अधिक बेहतर है और पक्ष प्रभाव सबूत stackoverflow.com/a/3430957/233906
Cerber

क्या HibernateJPA "@ फ़ैक्ट्री" और "@Externalizer" एनोटेशन का समर्थन करता है, यह है कि मैं कैसे OpenJPA लाइब्रेरी में डेटाटाइम utc हैंडलिंग करता हूं। stackoverflow.com/questions/10819862/…
जिनकी उम्र

44

Hibernate Dates में समय क्षेत्र के सामान से अनभिज्ञ है (क्योंकि वहाँ कोई भी नहीं है), लेकिन यह वास्तव में JDBC परत की वजह से समस्या है। ResultSet.getTimestampऔर PreparedStatement.setTimestampदोनों अपने डॉक्स में कहते हैं कि वे डेटाबेस से / पढ़ते और लिखते समय डिफ़ॉल्ट रूप से वर्तमान जेवीएम टाइमज़ोन से तारीखों को / में बदलते हैं।

मैं Hibernate 3.5 में इसे उप-समाधान द्वारा हल करता हूं org.hibernate.type.TimestampTypeजो इन JDBC विधियों को स्थानीय समय क्षेत्र के बजाय UTC का उपयोग करने के लिए मजबूर करता है:

public class UtcTimestampType extends TimestampType {

    private static final long serialVersionUID = 8088663383676984635L;

    private static final TimeZone UTC = TimeZone.getTimeZone("UTC");

    @Override
    public Object get(ResultSet rs, String name) throws SQLException {
        return rs.getTimestamp(name, Calendar.getInstance(UTC));
    }

    @Override
    public void set(PreparedStatement st, Object value, int index) throws SQLException {
        Timestamp ts;
        if(value instanceof Timestamp) {
            ts = (Timestamp) value;
        } else {
            ts = new Timestamp(((java.util.Date) value).getTime());
        }
        st.setTimestamp(index, ts, Calendar.getInstance(UTC));
    }
}

यदि आप उन प्रकारों का उपयोग करते हैं तो टाइमटेप और डेटटाइप को ठीक करने के लिए एक ही काम किया जाना चाहिए। नकारात्मक पक्ष यह है कि आपको मैन्युअल रूप से यह निर्दिष्ट करना होगा कि आपके POJOs में प्रत्येक दिनांक फ़ील्ड पर डिफ़ॉल्ट के बजाय इन प्रकारों का उपयोग किया जाना है (और शुद्ध JPA संगतता को भी तोड़ता है), जब तक कि किसी को अधिक सामान्य ओवरराइड विधि का पता न हो।

अद्यतन: हाइबरनेट 3.6 ने एपीआई प्रकार को बदल दिया है। 3.6 में, मैंने इसे लागू करने के लिए एक क्लास UtcTimestampTypeDescriptor लिखा।

public class UtcTimestampTypeDescriptor extends TimestampTypeDescriptor {
    public static final UtcTimestampTypeDescriptor INSTANCE = new UtcTimestampTypeDescriptor();

    private static final TimeZone UTC = TimeZone.getTimeZone("UTC");

    public <X> ValueBinder<X> getBinder(final JavaTypeDescriptor<X> javaTypeDescriptor) {
        return new BasicBinder<X>( javaTypeDescriptor, this ) {
            @Override
            protected void doBind(PreparedStatement st, X value, int index, WrapperOptions options) throws SQLException {
                st.setTimestamp( index, javaTypeDescriptor.unwrap( value, Timestamp.class, options ), Calendar.getInstance(UTC) );
            }
        };
    }

    public <X> ValueExtractor<X> getExtractor(final JavaTypeDescriptor<X> javaTypeDescriptor) {
        return new BasicExtractor<X>( javaTypeDescriptor, this ) {
            @Override
            protected X doExtract(ResultSet rs, String name, WrapperOptions options) throws SQLException {
                return javaTypeDescriptor.wrap( rs.getTimestamp( name, Calendar.getInstance(UTC) ), options );
            }
        };
    }
}

अब जब ऐप शुरू होता है, यदि आप टाइमस्टैम्पटाइपडस्क्रिप्ट। UtcTimestampTypeDescriptor के एक इंस्टेंस पर सेट करते हैं, तो सभी टाइमस्टैम्प को POJO पर एनोटेशन को बदलने के लिए बिना UTC में संग्रहीत और व्यवहार किया जाएगा। [मैंने अभी तक इसका परीक्षण नहीं किया है]


3
आप अपने रिवाज का उपयोग करने के लिए हाइबरनेट को कैसे बताते हैं UtcTimestampType?
डेरेक महार

डिवर्स्टोकलिंब, हाइबरनेट के किस संस्करण के साथ UtcTimestampTypeसंगत है?
डेरेक महार

2
"ResultSet.getTimestamp और ReadyedStatement.setTimestamp दोनों अपने डॉक्स में कहते हैं कि वे डेटाबेस से पढ़ने और लिखने पर डिफ़ॉल्ट रूप से दिनांक को वर्तमान JVM टाइमज़ोन से / से बदल देते हैं।" क्या आपके पास एक संदर्भ है? मैं इन विधियों के लिए जावा 6 Javadocs में इसका कोई उल्लेख नहीं देखता। के अनुसार stackoverflow.com/questions/4123534/... , कैसे इन तरीकों एक दिया करने के लिए समय क्षेत्र लागू Dateया Timestampहै JDBC ड्राइवर निर्भर।
डेरेक महार

1
मैं शपथ ले सकता था कि मैंने पिछले साल जेवीएम टाइमज़ोन का उपयोग करने के बारे में पढ़ा था, लेकिन अब मैं इसे नहीं खोज सकता। मैंने इसे एक विशिष्ट JDBC ड्राइवर के लिए डॉक्स पर पाया और सामान्यीकृत किया।
divestoclimb

2
काम करने के लिए आपके उदाहरण के 3.6 संस्करण को प्राप्त करने के लिए मुझे एक नया प्रकार बनाना था जो मूल रूप से टाइमस्टैम्प टाइप के आसपास एक आवरण था फिर उस प्रकार को फ़ील्ड पर सेट करें।
शॉन स्टोन

17

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

spring.jpa.properties.hibernate.jdbc.time_zone = UTC

फिर अपने इकाई वर्ग फ़ाइल में,

@Column
private LocalDateTime created;

11

एक ऐसा उत्तर जोड़ना जो पूरी तरह से शॉन स्टोन से संकेत के साथ divestoclimb पर आधारित हो। बस इसे विस्तार से बताना चाहते थे क्योंकि यह एक आम समस्या है और समाधान थोड़ा भ्रामक है।

यह हाइबरनेट 4.1.4 का उपयोग कर रहा है। हालांकि, मुझे संदेह है कि 3.6 के बाद कुछ भी काम करेगा।

सबसे पहले, divestoclimb का UtcTimestampTypeDescriptor बनाएं

public class UtcTimestampTypeDescriptor extends TimestampTypeDescriptor {
    public static final UtcTimestampTypeDescriptor INSTANCE = new UtcTimestampTypeDescriptor();

    private static final TimeZone UTC = TimeZone.getTimeZone("UTC");

    public <X> ValueBinder<X> getBinder(final JavaTypeDescriptor<X> javaTypeDescriptor) {
        return new BasicBinder<X>( javaTypeDescriptor, this ) {
            @Override
            protected void doBind(PreparedStatement st, X value, int index, WrapperOptions options) throws SQLException {
                st.setTimestamp( index, javaTypeDescriptor.unwrap( value, Timestamp.class, options ), Calendar.getInstance(UTC) );
            }
        };
    }

    public <X> ValueExtractor<X> getExtractor(final JavaTypeDescriptor<X> javaTypeDescriptor) {
        return new BasicExtractor<X>( javaTypeDescriptor, this ) {
            @Override
            protected X doExtract(ResultSet rs, String name, WrapperOptions options) throws SQLException {
                return javaTypeDescriptor.wrap( rs.getTimestamp( name, Calendar.getInstance(UTC) ), options );
            }
        };
    }
}

फिर UtcTimestampType बनाएँ, जो सुपर कंस्ट्रक्टर कॉल में SqlTypeDescriptor के रूप में TimestampTypeDescriptor के बजाय UtcTimestampTypeDescriptor का उपयोग करता है, लेकिन अन्यथा टाइमस्टैम्पटाइप के लिए सब कुछ प्रतिनिधि:

public class UtcTimestampType
        extends AbstractSingleColumnStandardBasicType<Date>
        implements VersionType<Date>, LiteralType<Date> {
    public static final UtcTimestampType INSTANCE = new UtcTimestampType();

    public UtcTimestampType() {
        super( UtcTimestampTypeDescriptor.INSTANCE, JdbcTimestampTypeDescriptor.INSTANCE );
    }

    public String getName() {
        return TimestampType.INSTANCE.getName();
    }

    @Override
    public String[] getRegistrationKeys() {
        return TimestampType.INSTANCE.getRegistrationKeys();
    }

    public Date next(Date current, SessionImplementor session) {
        return TimestampType.INSTANCE.next(current, session);
    }

    public Date seed(SessionImplementor session) {
        return TimestampType.INSTANCE.seed(session);
    }

    public Comparator<Date> getComparator() {
        return TimestampType.INSTANCE.getComparator();        
    }

    public String objectToSQLString(Date value, Dialect dialect) throws Exception {
        return TimestampType.INSTANCE.objectToSQLString(value, dialect);
    }

    public Date fromStringValue(String xml) throws HibernateException {
        return TimestampType.INSTANCE.fromStringValue(xml);
    }
}

अंत में, जब आप अपने हाइबरनेट कॉन्फ़िगरेशन को इनिशियलाइज़ करते हैं, तो UtcTimestampType को एक प्रकार के ओवरराइड के रूप में पंजीकृत करें:

configuration.registerTypeOverride(new UtcTimestampType());

अब टाइमस्टैम्प को JVM के समय क्षेत्र के साथ और उसके डेटाबेस से संबंधित नहीं होना चाहिए। HTH।


6
जेपीए और स्प्रिंग कॉन्फ़िगरेशन के लिए समाधान देखना बहुत अच्छा होगा।
ऑबर्जिन

2
हाइबरनेट के भीतर देशी प्रश्नों के साथ इस दृष्टिकोण का उपयोग करने के बारे में एक नोट। इन ओवरराइड प्रकारों का उपयोग करने के लिए आपको query.setParameter (int pos, Object value) के साथ मान सेट करना होगा, query.setParameter (int pos, Date value, TemporalType TemalType) नहीं। यदि आप बाद का उपयोग करते हैं तो हाइबरनेट अपने मूल प्रकार के कार्यान्वयन का उपयोग करेगा, क्योंकि वे हार्ड कोडित हैं।
निगेल

मुझे कथन कॉन्फ़िगरेशन कहां से कॉल करना चाहिए ।registerTypeOverride (नया UtcTimestampType ()); ?
स्टोनी

@ जहां भी आप अपने हाइबरनेट कॉन्फ़िगरेशन को इनिशियलाइज़ करते हैं। यदि आपके पास एक हाइबरनेट यूटिल (सबसे अधिक) है, तो यह वहां होगा।
शेन

1
यह काम करता है, लेकिन इसे जाँचने के बाद मुझे महसूस हुआ कि इसे टाइमज़ोन = "UTC" में काम करने वाले सर्वर के लिए आवश्यक नहीं है और सभी डिफ़ॉल्ट प्रकार के टाइमस्टैम्प को "टाइमस्टैम्प के साथ टाइम ज़ोन" के रूप में (यह स्वचालित रूप से तब किया जाता है)। लेकिन, यहाँ हाइबरनेट 4.3.5 GA के लिए पूर्ण एकल वर्ग के रूप में तय किया गया है और वसंत कारखाने बीन pastebin.com/tT4ACXn6
Lukasz Frankowski

10

आपको लगता है कि इस सामान्य समस्या पर हाइबरनेट द्वारा ध्यान दिया जाएगा। लेकिन ऐसा नहीं है! इसे सही करने के लिए कुछ "हैक" हैं।

मेरे द्वारा उपयोग की जाने वाली तारीख को डेटाबेस में एक लॉन्ग के रूप में संग्रहीत करना है। इसलिए मैं हमेशा 1/1/70 के बाद मिलीसेकंड के साथ काम कर रहा हूं। मेरे पास मेरे क्लास पर गेटर्स और सेटर हैं जो केवल डेट्स को वापस करते हैं / स्वीकार करते हैं। तो एपीआई वही रहता है। नीचे की ओर यह है कि मेरे पास डेटाबेस में लंबे समय तक है। एसओएल एसक्यूएल के साथ मैं बहुत ही कर सकता हूं <,>, = तुलना - फैंसी तारीख ऑपरेटरों नहीं।

एक और तरीका यह है कि यहाँ वर्णित के रूप में एक कस्टम मैपिंग प्रकार के उपयोगकर्ता हैं: http://www.hibernate.org/100.html

मुझे लगता है कि इससे निपटने का सही तरीका एक तारीख के बजाय एक कैलेंडर का उपयोग करना है। कैलेंडर के साथ आप कायम रखने से पहले TimeZone सेट कर सकते हैं।

नोट: मूर्खतापूर्ण स्टैकओवरफ़्लो मुझे टिप्पणी नहीं करने देगा, इसलिए यहाँ एक प्रतिक्रिया है

यदि आप शिकागो में यह वस्तु बनाते हैं:

new Date(0);

हाइबरनेट इसे "12/31/1969 18:00:00" के रूप में जारी रखता है। तिथियां समय-सीमा से रहित होनी चाहिए, इसलिए मुझे यकीन नहीं है कि समायोजन क्यों किया जाएगा।


1
मुझ पर शर्म की बात है! आप सही थे और आपकी पोस्ट की लिंक इसे अच्छे से समझाती है। अब मुझे लगता है कि मेरा जवाब कुछ नकारात्मक प्रतिष्ठा का हकदार है :)
डीएवी ए।

1
हर्गिज नहीं। आपने मुझे इस बात का बहुत स्पष्ट उदाहरण पोस्ट करने के लिए प्रोत्साहित किया कि यह समस्या क्यों है।
कोडफिंगर

4
मैं कैलेंडर ऑब्जेक्ट का उपयोग करके समय को सही ढंग से जारी रखने में सक्षम था ताकि वे डीबी में यूटीसी के रूप में संग्रहीत हों जैसा कि आपने सुझाव दिया था। हालाँकि, जब डेटाबेस से लगातार संस्थाओं को पढ़ना, हाइबरनेट मानते हैं कि वे स्थानीय समय क्षेत्र में हैं और कैलेंडर ऑब्जेक्ट गलत है!
जॉन के।

1
जॉन के, इस Calendarपढ़ने की समस्या को हल करने के लिए , मुझे लगता है कि हाइबरनेट या जेपीए को निर्दिष्ट करने के लिए कोई रास्ता प्रदान करना चाहिए, प्रत्येक मैपिंग के लिए, हाइबरनेट को जिस समय पढ़ना चाहिए और TIMESTAMPकॉलम पर लिखना चाहिए, उस समय क्षेत्र का अनुवाद करना चाहिए ।
डेरेक महार

joekutner, stackoverflow.com/questions/4123534/… को पढ़ने के बाद , मैं आपकी राय साझा करने के लिए आया हूं कि हमें डेटाबेस में युग के बाद से मिलीसेकंड को स्टोर करना चाहिए, बजाय इसके कि Timestampहम जरूरी नहीं कि JDBC ड्राइवर पर तारीखों को स्टोर करने के लिए भरोसा कर सकें। हम उम्मीद करेंगे।
डेरेक महार

8

यहां ऑपरेशन में कई टाइमज़ोन हैं:

  1. जावा की तिथि कक्षाएं (उपयोग और एसक्यूएल), जिसमें यूटीसी के निहित समय-क्षेत्र हैं
  2. आपके JVM में जो समयक्षेत्र चल रहा है, और
  3. आपके डेटाबेस सर्वर का डिफ़ॉल्ट समयक्षेत्र।

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

जेपीए / हाइबरनेट का उपयोग करके (आसानी से) टाइमज़ोन को स्टोर करने की क्षमता के बिना तो जानकारी खो जाती है और एक बार जानकारी खो जाने के बाद इसका निर्माण करना महंगा हो जाता है (यदि संभव हो तो)।

मैं यह तर्क दूंगा कि हमेशा समयक्षेत्र की जानकारी को संग्रहीत करना बेहतर होना चाहिए (डिफ़ॉल्ट होना चाहिए) और उपयोगकर्ताओं के पास समय-समय को दूर करने की वैकल्पिक क्षमता होनी चाहिए (हालाँकि यह वास्तव में केवल प्रदर्शन को प्रभावित करता है, फिर भी किसी भी तिथि में अंतर्निहित समय क्षेत्र है)।

क्षमा करें, यह पोस्ट काम-काज प्रदान नहीं करती है (जिसका उत्तर अन्यत्र दिया गया है) लेकिन यह इस बात का युक्तिकरण है कि हमेशा समय-सीमा की जानकारी को संग्रहीत करना क्यों महत्वपूर्ण है। दुर्भाग्य से ऐसा लगता है कि कई कंप्यूटर वैज्ञानिक और प्रोग्रामिंग व्यवसायी टाइमज़ोन की आवश्यकता के खिलाफ तर्क देते हैं, क्योंकि वे "जानकारी के नुकसान" के परिप्रेक्ष्य की सराहना नहीं करते हैं और यह कैसे अंतर्राष्ट्रीयकरण जैसी चीजों को बहुत मुश्किल बना देता है - जो इन दिनों वेब साइटों द्वारा सुलभ के साथ बहुत महत्वपूर्ण है क्लाइंट और आपके संगठन के लोग जैसे ही वे दुनिया भर में जाते हैं।


1
"हाइबरनेट / जेपीए में एक गंभीर डिजाइन की कमी है" मैं कहता हूं कि यह एसक्यूएल में कमी है, जो परंपरागत रूप से समय-क्षेत्र को निहित करने की अनुमति देता है, और इसलिए संभवतः कुछ भी। सिली एसक्यूएल।
रायडवल

3
दरअसल, टाइमजोन को हमेशा स्टोर करने के बजाय, आप एक टाइमज़ोन (आमतौर पर यूटीसी) पर भी मानकीकरण कर सकते हैं, और इस टाइमज़ोन में सब कुछ कन्वर्ट कर सकते हैं जब लगातार (और पढ़ते समय वापस)। यह वही है जो हम आमतौर पर करते हैं। हालाँकि, JDBC सीधे समर्थन नहीं करता है: - /।
15:25 बजे साल्के

3

कृपया सोर्सफोर्ज पर मेरी परियोजना पर एक नज़र डालें जिसमें मानक SQL दिनांक और समय प्रकारों के साथ-साथ JSR 310 और Joda Time के लिए उपयोगकर्ता प्रकार हैं। सभी प्रकार ऑफ़सेटिंग समस्या को हल करने का प्रयास करते हैं। देखHttp://sourceforge.net/projects/usertype/

संपादित करें: डेरेक महार की इस टिप्पणी से जुड़े सवाल के जवाब में:

"क्रिस, अपने उपयोगकर्ता प्रकार हाइबरनेट 3 या अधिक के साथ काम करते हैं? - डेरेक महार 7 7 '10 12:30 पर"

हां ये प्रकार हाइबरनेट 3.6 सहित हाइबरनेट 3.x संस्करणों का समर्थन करते हैं।


2

दिनांक किसी भी समय क्षेत्र में नहीं है (यह सभी के लिए समान समय में एक निर्धारित समय से एक मिलीसेकंड कार्यालय है), लेकिन अंतर्निहित (आर) डीबी आमतौर पर राजनीतिक प्रारूप (वर्ष, माह, दिन, घंटा, मिनट, दूसरा) में टाइमस्टैम्प को संग्रहीत करते हैं। ..) वह समय-क्षेत्र संवेदनशील है।

गंभीर होने के लिए, हाइबरनेट MUST को किसी प्रकार की मैपिंग के भीतर बताया जा सकता है कि DB दिनांक इस तरह के और इस तरह के टाइमज़ोन में है ताकि जब यह लोड हो जाए या इसे स्टोर किया जाए तो यह अपने आप नहीं लगता ...


1

मुझे बस उसी समस्या का सामना करना पड़ा जब मैं यूटीसी के रूप में डीबी में तारीखों को संग्रहीत करना चाहता था और उपयोग varcharऔर स्पष्ट से बचेंString <-> java.util.Date यूटीसी टाइम ज़ोन में अपने संपूर्ण जावा ऐप रूपांतरण करने , क्योंकि अगर जेवीएम होता है तो यह एक और अप्रत्याशित समस्या पैदा कर सकता है। कई अनुप्रयोगों में साझा किया गया)।

तो, एक ओपन सोर्स प्रोजेक्ट है DbAssist, जो आपको डेटाबेस से UTC तारीख के रूप में आसानी से रीड / राइट को ठीक करने की अनुमति देता है। चूंकि आप इकाई में फ़ील्ड्स को मैप करने के लिए जेपीए एनोटेशन का उपयोग कर रहे हैं, आपको बस इतना करना है कि अपनी मावेन pomफ़ाइल के लिए निम्न निर्भरता को शामिल करें :

<dependency>
    <groupId>com.montrosesoftware</groupId>
    <artifactId>DbAssist-5.2.2</artifactId>
    <version>1.0-RELEASE</version>
</dependency>

फिर आप @EnableAutoConfigurationस्प्रिंग एप्लिकेशन क्लास से पहले एनोटेशन जोड़कर फिक्स (हाइबरनेट + स्प्रिंग बूट उदाहरण के लिए) लागू करते हैं । अन्य इंस्टॉलेशन इंस्टॉलेशन निर्देशों और अधिक उपयोग उदाहरणों के लिए, बस प्रोजेक्ट के गीथूब को देखें

अच्छी बात यह है कि आपको संस्थाओं को बिल्कुल भी संशोधित नहीं करना है; आप उनके java.util.Dateखेतों को छोड़ सकते हैं जैसे वे हैं।

5.2.2आपके द्वारा उपयोग किए जा रहे हाइबरनेट संस्करण के अनुरूप है। मुझे यकीन नहीं है कि आप अपनी परियोजना में किस संस्करण का उपयोग कर रहे हैं, लेकिन प्रदान किए गए फ़िक्सेस की पूरी सूची परियोजना के गीथूब के विकी पृष्ठ पर उपलब्ध है । विभिन्न हाइबरनेट संस्करणों के लिए फ़िक्स अलग है, इसका कारण यह है कि हाइबरनेट रचनाकारों ने एपीआई को रिलीज के बीच कई बार बदल दिया।

आंतरिक रूप से, फिक्स कस्टम बनाने के लिए divestoclimb, Shane और कुछ अन्य स्रोतों से संकेत का उपयोग करता है UtcDateType। फिर यह java.util.Dateकस्टम के साथ मानक को मैप करता है UtcDateTypeजो सभी आवश्यक समय क्षेत्र को संभालता है। @Typedefप्रदान की गई package-info.javaफ़ाइल में एनोटेशन का उपयोग करके प्रकारों की मैपिंग प्राप्त की जाती है।

@TypeDef(name = "UtcDateType", defaultForType = Date.class, typeClass = UtcDateType.class),
package com.montrosesoftware.dbassist.types;

आप यहां एक लेख पा सकते हैं, जिसमें बताया गया है कि इस तरह की टाइम शिफ्ट बिल्कुल क्यों होती है और इसे हल करने के लिए क्या दृष्टिकोण हैं।


1

हाइबरनेट एनोटेशन या किसी अन्य माध्यम से समय क्षेत्र निर्दिष्ट करने की अनुमति नहीं देता है। यदि आप तिथि के बजाय कैलेंडर का उपयोग करते हैं, तो आप HIbernate संपत्ति AccessType का उपयोग करके एक वर्कअराउंड को लागू कर सकते हैं और स्वयं मानचित्रण को लागू कर सकते हैं। अधिक उन्नत समाधान एक कस्टम UserType को लागू करने के लिए अपनी तिथि या कैलेंडर को मैप करना है। दोनों समाधानों को यहाँ मेरे ब्लॉग पोस्ट में समझाया गया है: http://www.joobik.com/2010/11/mapping-dates-and-time-zones-ith.html

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