सीतनिद्रा में होना, @SequenceGenerator और आवंटन करना


117

हम सभी का उपयोग करते समय हाइबरनेट के डिफ़ॉल्ट व्यवहार को जानते हैं @SequenceGenerator- यह एक के बाद एक वास्तविक डेटाबेस अनुक्रम को बढ़ाता है , इस मान को 50 (डिफ़ॉल्ट allocationSizeमान) से कई गुणा बढ़ाता है और फिर इस मान को इकाई आईडी के रूप में उपयोग करता है।

यह गलत व्यवहार और विनिर्देश के साथ संघर्ष है जो कहता है:

आबंटित करें - (वैकल्पिक) अनुक्रम से अनुक्रम संख्या आवंटित करते समय वेतन वृद्धि की राशि।

स्पष्ट होने के लिए: मैं उत्पन्न आईडी के बीच अंतराल के बारे में परेशान नहीं करता हूं।

मुझे उन आईडी की परवाह है जो अंतर्निहित डेटाबेस अनुक्रम के अनुरूप नहीं हैं । उदाहरण के लिए: कोई भी अन्य एप्लिकेशन (जैसे कि सादा JDBC का उपयोग करता है) अनुक्रम से प्राप्त आईडी के तहत नई पंक्तियाँ सम्मिलित करना चाह सकता है - लेकिन वे सभी मान पहले से ही हाइबरनेट द्वारा उपयोग किए जा सकते हैं! पागलपन।

क्या किसी को इस समस्या का कोई हल पता है (बिना सेटिंग allocationSize=1और इस तरह प्रदर्शन में गिरावट)?

EDIT:
चीजों को स्पष्ट करने के लिए। यदि अंतिम सम्मिलित रिकॉर्ड में ID = था 1, तो HB 51, 52, 53...अपनी नई संस्थाओं BUT के लिए एक ही समय में मानों का उपयोग करता है: डेटाबेस में अनुक्रम का मान सेट किया जाएगा 2। जब अन्य अनुप्रयोग उस अनुक्रम का उपयोग कर रहे हैं, तो आसानी से त्रुटियां हो सकती हैं।

Othe हाथ पर: विनिर्देश कहता है (मेरी समझ में) कि डेटाबेस अनुक्रम को सेट किया जाना चाहिए था 51और इस बीच HB को रेंज से मानों का उपयोग करना चाहिए 2, 3 ... 50


अद्यतन:
जैसा कि स्टीव आइबर्सोल ने नीचे उल्लेख किया है: मेरे द्वारा वर्णित व्यवहार (और कई के लिए सबसे सहज भी) सेटिंग द्वारा सक्षम किया जा सकता है hibernate.id.new_generator_mappings=true

आप सभी का धन्यवाद।

अद्यतन 2:
भविष्य के पाठकों के लिए, नीचे आप एक कार्यकारी उदाहरण पा सकते हैं।

@Entity
@Table(name = "users")
public class User {

    @Id
    @GeneratedValue(strategy = GenerationType.SEQUENCE, generator = "USERS_SEQ")
    @SequenceGenerator(name = "USERS_SEQ", sequenceName = "SEQUENCE_USERS")
    private Long id;
}

persistence.xml

<persistence-unit name="testPU">
  <properties>
    <property name="hibernate.id.new_generator_mappings" value="true" />
  </properties>
</persistence-unit>

2
"बिना आबंटन को आबंटित किए बिना = 1 और इस प्रकार प्रदर्शन को नीचा दिखाना" आप इसे नीचा दिखाने के लिए इसे क्यों 1 पर सेट करते हैं?
sheidaei 12

3
@sheidaei देख सकते हैं नीचे टिप्पणी कर सकते हैं :-) यह इसलिए है क्योंकि saveअनुक्रम के अगले मूल्य के लिए डेटाबेस को क्वेरी करने की आवश्यकता है।
जी डेमेकी

धन्यवाद, आप एक ही मुद्दे का सामना कर रहे थे। सबसे पहले मैं हर @SequenceGenerator में आबंटन = 1 जोड़ रहा था। Hibernate.id.new_generator_mappings = true का उपयोग करना रोकें। हालाँकि JPA अभी भी डेटाबेस को प्रत्येक इंसर्ट के लिए id प्राप्त करने के लिए क्वेरी करता है ...
TheBakker

1
SequenceGeneratorहाइबरनेट के साथ डेटाबेस को केवल तभी क्वेरी करेगा जब आईडी की राशि allocationsizeरन आउट द्वारा निर्दिष्ट की गई हो। यदि आप सेट करते हैं allocationSize = 1तो यही कारण है कि हाइबरनेट प्रत्येक डीबी के लिए डीबी को क्वेरी करता है। इस मान को बदलें, और आप कर रहे हैं।
जी। डेमेकी

1
धन्यवाद! hibernate.id.new_generator_mappingsसेटिंग वास्तव में महत्वपूर्ण है। मुझे आशा है कि यह डिफ़ॉल्ट सेटिंग है कि मुझे इतना समय अनुसंधान खर्च करने की आवश्यकता नहीं है कि आईडी संख्या जंगली क्यों जाती है।
लियोन - हान ली

जवाबों:


43

बिल्कुल स्पष्ट होने के लिए ... आप जो भी वर्णन करते हैं वह किसी भी तरह से कल्पना के साथ संघर्ष नहीं करता है । हाइबरनेट उन मूल्यों के बारे में बात करता है जो आपकी संस्थाओं को असाइन करते हैं, न कि उन मूल्यों को जो वास्तव में डेटाबेस अनुक्रम में संग्रहीत होते हैं।

हालाँकि, आपके द्वारा खोजे जा रहे व्यवहार को प्राप्त करने का विकल्प है। पहले मेरा जवाब देखें कि क्या जेपीए एनोटेशन और हाइबरेट का उपयोग करके @GeneratedValue रणनीति को गतिशील रूप से चुनने का एक तरीका है? यह आपको मूल बातें देगा। जब तक आप उस SequenceStyleGenerator का उपयोग करने के लिए सेट किए जाते हैं, तब तक हाइबरनेट SequenceStyleGenerator allocationSizeमें "पूल किए गए ऑप्टिमाइज़र" का उपयोग करके व्याख्या करेगा । "पूल किए गए ऑप्टिमाइज़र" डेटाबेस के उपयोग के लिए है जो अनुक्रमों के निर्माण पर "वेतन वृद्धि" विकल्प की अनुमति देता है (सभी डेटाबेस जो अनुक्रमों का समर्थन करते हैं, एक वेतन वृद्धि का समर्थन करते हैं)। वैसे भी, वहाँ विभिन्न अनुकूलक रणनीतियों के बारे में पढ़ें।


धन्यवाद स्टीव! सबसे अच्छा जवाब। साथ ही आपकी अन्य पोस्ट सहायक थी।
जी डेमेकी

4
मैंने यह भी देखा कि आप सह-लेखक हैं org.hibernate.id.enhanced.SequenceStyleGenerator। तुमने मुझे डरा दिया।
जी डेमेकी

22
आपको आश्चर्य हुआ कि कैसे? मैं हाइबरनेट का मुख्य विकासक हूं। मैंने कई हाइबरनेट कक्षाएं लिखी / सह-लिखी हैं;)
स्टीव एबर्सोल

सिर्फ रिकार्ड के लिए। बड़े अंतराल को रोकने के लिए DB अनुक्रम वृद्धि से बचा जाना चाहिए। डीबी अनुक्रम आवंटन से गुणा किया जाता है जब आईडी कैश
निकलता है। अधिक

1
विश्व स्तर पर उपयोग किए जाने वाले "ऑप्टिमाइज़र" को बदलने का एक तरीका यह है कि आप अपने हाइबरनेट विकल्पों में कुछ इस तरह से जोड़ें: serviceBuilder.applySetting ("hibernate.id.optimizer.pooled.preferred", LegacyHiLoAlgorithmOptimizer.class.getName ()); LegacyHiLoAlgorithOptimizer के बजाय आप किसी भी ऑप्टिमाइज़र वर्ग को चुन सकते हैं, और यह डिफ़ॉल्ट हो जाएगा। यह बिना किसी एनोटेशन को बदले व्यवहार को आप डिफ़ॉल्ट रूप में रखना आसान बना सकते हैं। इसके अलावा, "पूल किए गए" और "हिलो" ऑप्टिमाइज़र के साथ देखें: ये अजीब परिणाम देते हैं जब आपका अनुक्रम मान 0 पर शुरू होता है, जिससे नकारात्मक आईडी होती है।
fjalvingh

17

allocationSize=1यह एक माइक्रो ऑप्टिमाइज़ेशन है जो क्वेरी हाइबरनेट को आवंटन की सीमा में मान देने की कोशिश करता है और इसलिए अनुक्रम से क्वेरी डेटाबेस से बचने की कोशिश करता है। लेकिन अगर आप इसे 1 पर सेट करते हैं, तो यह क्वेरी हर बार निष्पादित की जाएगी। इससे कोई अंतर नहीं पड़ता है क्योंकि यदि आपका डेटा बेस किसी अन्य एप्लिकेशन द्वारा एक्सेस किया जाता है, तो यह समस्या पैदा करेगा यदि उसी आईडी का उपयोग किसी अन्य एप्लिकेशन द्वारा किया जाता है।

अगली पीढ़ी की अनुक्रम आईडी आवंटन पर आधारित है।

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

इसलिए आपको हमेशा उपयोग allocationSize=1करते समय उपयोग करना चाहिए SequenceGenerator। के रूप में अंतर्निहित डेटाबेस अनुक्रम के अधिकांश के लिए हमेशा वेतन वृद्धि होती है 1


12
प्रदर्शन से कुछ नहीं होगा? क्या आपको वाकई यकीन है? मुझे सिखाया गया है कि allocationSize=1हर saveऑपरेशन पर हाइबरनेट के साथ नई आईडी मान प्राप्त करने के लिए डेटाबेस की यात्रा करने की आवश्यकता है।
जी डेमेकी

2
यह एक माइक्रो ऑप्टिमाइज़ेशन है जिसमें क्वेरी हाइबरनेट को श्रेणी में मान असाइन करने की कोशिश की जाती है allocationSizeऔर इसलिए अनुक्रम के लिए क्वेरी डेटाबेस से बचने का प्रयास करें। यदि आप इसे 1 पर सेट करते हैं, तो यह क्वेरी हर बार निष्पादित की जाएगी। इससे शायद ही कोई फर्क पड़ता है यदि आपका डेटा बेस किसी अन्य एप्लिकेशन द्वारा एक्सेस किया जाता है, तो यह समस्याएं पैदा करेगा यदि उसी आईडी का उपयोग किसी अन्य एप्लिकेशन द्वारा किया जाता है
अमित देशपांडे

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

2
ठीक है। सब कुछ अनुप्रयोग विशिष्ट है, है ना! यदि आपका आवेदन केवल पढ़ने के लिए किया गया आवेदन है तो आवंटन आकार 1000 या 1 का उपयोग करने का प्रभाव बिल्कुल 0. दूसरी तरफ ऐसी चीजें हैं जो सबसे अच्छी प्रथाएं हैं। यदि आप उन सर्वोत्तम प्रथाओं का सम्मान नहीं करते हैं जो वे एकत्र करते हैं और संयुक्त प्रभाव होगा तो आपका आवेदन सुस्त हो जाएगा। एक और उदाहरण एक लेनदेन शुरू करना होगा जब आपको बिल्कुल एक की आवश्यकता नहीं होगी।
हसन सीलन

1

स्टीव एबर्सोल और अन्य सदस्य,
क्या आप कृपया बड़े अंतर के साथ आईडी का कारण बताएंगे (डिफ़ॉल्ट रूप से 50)? मैं हाइबरनेट 4.2.15 का उपयोग कर रहा हूं और निम्नलिखित कोड org.hibernate.id.enhanced.OptimizerFactory कैस में पाया।

if ( lo > maxLo ) {
   lastSourceValue = callback.getNextValue();
   lo = lastSourceValue.eq( 0 ) ? 1 : 0;
   hi = lastSourceValue.copy().multiplyBy( maxLo+1 ); 
}  
value = hi.copy().add( lo++ );

जब भी यह स्टेटमेंट के अंदर से टकराता है, तो हाई वैल्यू बहुत बड़ी हो जाती है। इसलिए, लगातार सर्वर पुनरारंभ के साथ परीक्षण के दौरान मेरी आईडी निम्नलिखित अनुक्रम आईडी उत्पन्न करती है:
1, 2, 3, 4, 19, 250, 251, 252, 400, 550, 750, 751, 752, 850, 1100, 1150।

मुझे पता है कि आपने पहले ही कहा था कि यह युक्ति से टकराव नहीं था, लेकिन मेरा मानना ​​है कि यह अधिकांश डेवलपर्स के लिए बहुत अप्रत्याशित स्थिति होगी।

किसी का भी इनपुट काफी मददगार होगा।

Jihwan

अद्यतन: ne1410s: संपादन के लिए धन्यवाद।
cfrick: ठीक है। मै वो कर लूंगा। यह मेरी पहली पोस्ट थी और यह सुनिश्चित नहीं था कि इसका उपयोग कैसे किया जाए।

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

उदाहरण के लिए, अनुक्रम आईडी एक बिंदु पर 1 था और हाइबरनेट ने 5, 6, 7, 8, 9 (आवंटन के साथ = 1) में प्रवेश किया। अगली बार, जब हम अगला अनुक्रम संख्या प्राप्त करते हैं, DB 2 लौटता है, लेकिन हाइबरनेट को 10, 11, 12 ... का उपयोग करने की आवश्यकता होती है, इसलिए, "hi = lastSourceValue.copy ()। MultlyBy (maxLo + 1") है। डीबी अनुक्रम से लौटे 2 में से एक अगली आईडी 10 प्राप्त करने के लिए उपयोग किया जाता है। ऐसा लगता है कि केवल परेशान करने वाली बात लगातार सर्वर के पुनरारंभ के दौरान थी और बड़े अंतर के साथ यह मेरा मुद्दा था।

इसलिए, जब हम SEQUENCE ID का उपयोग करते हैं, तो तालिका में सम्मिलित आईडी DB में SEQUENCE नंबर के साथ मेल नहीं खाएगी।


1

हाइबरनेट स्रोत कोड और नीचे विन्यास में खुदाई करने के बाद 50 आवेषण के बाद अगले मूल्य के लिए Oracle db जाता है। इसलिए प्रत्येक बार कॉल करने के बाद अपना INST_PK_SEQ 50 बढ़ाएँ।

नीचे की रणनीति के लिए हाइबरनेट 5 का उपयोग किया जाता है

नीचे भी की जाँच करें http://docs.jboss.org/hibernate/orm/5.1/userguide/html_single/Hibernate_User_Guide.html#identifiers-generators-sequence

@Id
@Column(name = "ID")
@GenericGenerator(name = "INST_PK_SEQ", 
strategy = "org.hibernate.id.enhanced.SequenceStyleGenerator",
parameters = {
        @org.hibernate.annotations.Parameter(
                name = "optimizer", value = "pooled-lo"),
        @org.hibernate.annotations.Parameter(
                name = "initial_value", value = "1"),
        @org.hibernate.annotations.Parameter(
                name = "increment_size", value = "50"),
        @org.hibernate.annotations.Parameter(
                name = SequenceStyleGenerator.SEQUENCE_PARAM, value = "INST_PK_SEQ"),
    }
)
@GeneratedValue(strategy = GenerationType.SEQUENCE, generator = "INST_PK_SEQ")
private Long id;

3
क्षमा करें, लेकिन यह किसी चीज़ को सेट करने का एक अत्यंत क्रियात्मक तरीका है, जिसे पूरे हाइबरनेट के लिए दो मापदंडों के साथ आसानी से व्यक्त किया जा सकता है और इस प्रकार सभी संस्थाओं के लिए।
जी। डेमेकी

सच है, लेकिन जब मैं अन्य तरीकों से कोशिश करता हूं तो उनमें से कोई भी काम नहीं करता है अगर आपके पास यह काम है तो मुझे भेज सकते हैं कि आपने कैसे कॉन्फ़िगर किया है
fatih tekin

मैंने अपना उत्तर अपडेट कर दिया है - अब इसमें एक कार्यशील उदाहरण भी शामिल है। यद्यपि मेरी उपरोक्त टिप्पणी आंशिक रूप से गलत है: दुर्भाग्य से, आप सभी संस्थाओं के लिए न तो allocationSizeऔर न ही initialValueविश्व स्तर पर सेट कर सकते हैं (जब तक कि केवल एक जनरेटर का उपयोग न करें, लेकिन IMHO यह बहुत पठनीय नहीं है)।
जी डेमेकी

1
स्पष्टीकरण के लिए धन्यवाद, लेकिन आपने जो ऊपर लिखा है, मैंने कोशिश की है और यह हाइबरनेट 5.0.7 के साथ काम नहीं करता है। तब मैंने इस लक्ष्य को प्राप्त करने में सक्षम होने के लिए स्रोत कोड में खुदाई की है और वह कार्यान्वयन है जिसे मैं खोजने में सक्षम था हाइबरनेट स्रोत कोड में। कॉन्फ़िगर करना बुरा लग सकता है, लेकिन यह दुर्भाग्य से एपी को हाइबरनेट करता है और मैं हाइबरनेट के मानक
एंटिटी मैनजर

1

मुझे भी हाइबरनेट 5 में इस मुद्दे का सामना करना पड़ा:

@Id
@GeneratedValue(strategy = GenerationType.SEQUENCE, generator = SEQUENCE)
@SequenceGenerator(name = SEQUENCE, sequenceName = SEQUENCE)
private Long titId;

नीचे इस तरह की चेतावनी मिली:

पदावनत का पाया गया उपयोग [org.hibernate.id.SequenceHiLoGenerator] अनुक्रम-आधारित आईडी जनरेटर; इसके बजाय org.hibernate.id.enhanced.SequenceStyleGenerator का उपयोग करें। विवरण के लिए हाइबरनेट डोमेन मॉडल मैपिंग गाइड देखें।

फिर मेरे कोड को SequenceStyleGenerator में बदल दिया:

@Id
@GenericGenerator(name="cmrSeq", strategy = "org.hibernate.id.enhanced.SequenceStyleGenerator",
        parameters = {
                @Parameter(name = "sequence_name", value = "SEQUENCE")}
)
@GeneratedValue(generator = "sequence_name")
private Long titId;

इससे मेरे दो मुद्दे हल हो गए:

  1. पदावनत चेतावनी तय है
  2. अब oracle क्रम के अनुसार id जनरेट की गई है।

0

मैं स्कीमा में अनुक्रम के लिए डीडीएल की जांच करूंगा। जेपीए कार्यान्वयन केवल सही आवंटन आकार के साथ अनुक्रम के निर्माण के लिए जिम्मेदार है। इसलिए, यदि आबंटन का आकार 50 है तो आपके अनुक्रम में इसके डीडीएल में 50 की वृद्धि होनी चाहिए।

यह मामला आमतौर पर आवंटन आकार 1 के साथ अनुक्रम के निर्माण के साथ हो सकता है फिर बाद में आवंटन आकार 50 (या डिफ़ॉल्ट) में कॉन्फ़िगर किया गया है लेकिन अनुक्रम DDL अपडेट नहीं किया गया है।


आप मेरी बात को गलत समझ रहे हैं। ALTER SEQUENCE ... INCREMENTY BY 50;कुछ भी हल नहीं होगा, क्योंकि समस्या अभी भी वही है। अनुक्रम मूल्य अभी भी वास्तविक संस्थाओं आईडी को प्रतिबिंबित नहीं करता है।
जी डेमेकी

कृपया एक परीक्षण मामला साझा करें ताकि हम यहां की समस्या को बेहतर ढंग से समझ सकें।
हसन सीलन

1
परीक्षण का मामला? क्यों? मेरे द्वारा पोस्ट किया गया प्रश्न इतना जटिल नहीं था और पहले ही उत्तर दिया जा चुका है। ऐसा लगता है कि आपको नहीं पता है कि हायलो जनरेटर कैसे काम करता है। वैसे भी: अपना समय और प्रयास बलिदान करने के लिए धन्यवाद।
जी डेमेकी

1
ग्रेगरी, वास्तव में मुझे पता है कि मैं किस बारे में बात कर रहा हूं, मैंने बाटू जेपीए लिखा है जो कि 100 100 जेपीए कार्यान्वयन है जो वर्तमान में अपने ऊष्मायन में है और गति के मामले में हाइबरनेट को हराता है - 15 गुना तेज। दूसरी ओर, मैंने आपके प्रश्न को गलत समझा होगा और यह नहीं सोचा था कि सीक्वेंस के साथ हाइबरनेट का उपयोग करने से कोई समस्या पैदा हो सकती है क्योंकि मैंने 2003 से कई डेटाबेस में कई प्रोजेक्ट्स में हाइबरनेट का उपयोग किया है। महत्वपूर्ण बात यह है कि आपको इस प्रश्न का हल मिल गया है, क्षमा करें, मैं उत्तर को सही
हसन सीलन

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