दिलचस्प पोस्ट
रूबी में बेस 64 एन्कोडेड स्ट्रिंग में अजीब \ n लोग base128 का उपयोग क्यों नहीं करते हैं? सी कोड आसानी से कैसे बेंचमार्क कर सकता हूं? एसएपी। नेट एमवीसी 2 के साथ काम करने के लिए एसक्यूएल सर्वर कॉम्पैक्ट 3.5 / 4 नहीं मिल सकता है Node.js में प्रबंध सत्र? पाठ को कैसे दिखाया जाए, एक बिंदीदार रेखा तो पृष्ठ की चौड़ाई फैले जाने वाले पाठ? एचडीएफ 5 – संगामी, संपीड़न और I / O प्रदर्शन त्रुटि "पहले से ही एक खुली DataReader इस कमान के साथ जुड़ा हुआ है जो पहले बंद होना चाहिए" जब 2 अलग आदेशों का उपयोग करते हुए Enum.hashCode () के पीछे क्या कारण है? दृश्य स्टूडियो 2010 प्रोफेशनल में अनुरोधित नेट फ्रेमवर्क डेटा प्रदाता को ढूँढने में असमर्थ बैश में एक फ़ाइल से यादृच्छिक पंक्तियां चुनें PHP + MySQL + संग्रहीत कार्यविधि, मैं एक "आउट" मान कैसे प्राप्त कर सकता हूं? ईएस 6 वाक्यविन्यास और बैबल के साथ जावास्क्रिप्ट में त्रुटि को बढ़ाते हुए विधानसभा भाषा में मोड को संबोधित करना (IA-32 NASM) कैसे DataGridView में प्रोग्रामिंग सेल मूल्य निर्धारित करने के लिए?

हाइबरनेट जेपीए अनुक्रम (गैर-आईडी)

क्या कुछ स्तंभ के लिए एक डीबी अनुक्रम का उपयोग करना संभव है जो पहचानकर्ता नहीं है / समग्र पहचानकर्ता का हिस्सा नहीं है ?

मैं सीतनिद्रा में होना जेपीए प्रदाता के रूप में उपयोग कर रहा हूं, और मेरे पास एक मेज है जिसमें कुछ कॉलम हैं जो मूल्यों को तैयार करते हैं (अनुक्रम का उपयोग करते हुए), हालांकि वे पहचानकर्ता का हिस्सा नहीं हैं।

मैं क्या चाहता हूं एक इकाई के लिए एक नया मान बनाने के लिए एक अनुक्रम का उपयोग करना है, जहां अनुक्रम के लिए कॉलम प्राथमिक कुंजी नहीं है (का भाग):

@Entity @Table(name = "MyTable") public class MyEntity { //... @Id //... etc public Long getId() { return id; } //note NO @Id here! but this doesn't work... @GeneratedValue(strategy = GenerationType.AUTO, generator = "myGen") @SequenceGenerator(name = "myGen", sequenceName = "MY_SEQUENCE") @Column(name = "SEQ_VAL", unique = false, nullable = false, insertable = true, updatable = true) public Long getMySequencedValue(){ return myVal; } } 

तब जब मैं यह करता हूं:

 em.persist(new MyEntity()); 

आईडी जनरेट किया जाएगा, लेकिन मेरी mySequenceVal संपत्ति मेरे जेपीए प्रदाता द्वारा भी तैयार की जाएगी।

बस चीजों को स्पष्ट करने के लिए: मैं हाइबरनेट चाहता हूं कि mySequencedValue प्रॉपर्टी के लिए मूल्य उत्पन्न करे। मुझे पता है सीतनिद्रा में होना डेटाबेस से बने मूल्यों को संभाल सकता है, लेकिन मैं अपनी संपत्ति के मूल्य को उत्पन्न करने के लिए खुद को हाइबरनेट के अलावा एक ट्रिगर या किसी अन्य चीज का उपयोग नहीं करना चाहता हूं यदि सीतनिद्रा में होना प्राथमिक कुंजी के लिए मूल्य उत्पन्न कर सकता है, तो यह एक साधारण संपत्ति के लिए क्यों नहीं पैदा कर सकता है?

Solutions Collecting From Web of "हाइबरनेट जेपीए अनुक्रम (गैर-आईडी)"

इस समस्या के उत्तर की तलाश में, मैं इस लिंक पर ठोकर खाई

ऐसा लगता है कि सीतनिद्रा में होना / जेपीए स्वचालित रूप से अपने गैर-आईडी गुणों के लिए एक मूल्य बनाने में सक्षम नहीं है @GeneratedValue एनोटेशन का प्रयोग केवल @Id के साथ संयोजन के रूप में किया जाता है ताकि ऑटो-नंबर बनाए जाएं।

@GeneratedValue एनोटेशन सिर्फ हाइबरनेट को बताता है कि डेटाबेस इस वैल्यू को खुद ही पैदा कर रहा है।

उस फोरम में सुझाए गए समाधान (या काम के आसपास) उत्पन्न आईडी के साथ एक अलग इकाई बनाने के लिए है, कुछ ऐसा:

 @Entity
 सार्वजनिक वर्ग जनरल स्यूक्वेंस नंबर {
   @Id
   @GeneratedValue (...)
   निजी लंबी संख्या;
 }

 @Entity 
 सार्वजनिक वर्ग माइरेन्टी {
   @ आईडी ..
   निजी लांग आईडी;

   @एक से एक(...)
   प्राइवेट जनरलसैक्यूनसम्बर मेरीवैल;
 }

मैंने पाया कि @Column(columnDefinition="serial") सही काम करता है लेकिन केवल PostgreSQL के लिए मेरे लिए यह सही समाधान था, क्योंकि दूसरी इकाई "बदसूरत" विकल्प है।

सीतनिद्रा में होना निश्चित रूप से इस का समर्थन करता है डॉक्स से:

"जनरेटेड प्रॉपर्टी गुण हैं, जो उनके मानकों को डेटाबेस से उत्पन्न होती हैं। आमतौर पर, सीतनिद्रा में होना अनुप्रयोगों को ऑब्जेक्ट्स को ताज़ा करने के लिए आवश्यक होता है जिसमें कोई भी संपत्ति होती है जिसके लिए डेटाबेस मूल्य पैदा कर रहा था। उत्पन्न गुणों को चिह्नित करते हुए, हालांकि, अनुप्रयोग प्रतिनिधि को यह हाइबरनेट के लिए जिम्मेदारी देता है अनिवार्य रूप से, जब भी सीतनिद्रा में होना एक एसक्यूएल INSERT या एक इकाई के लिए अद्यतन जो उत्पन्न गुण परिभाषित किया है, यह तत्काल एक चयन के बाद उत्पन्न मानों को प्राप्त करने के लिए का चयन करें।

केवल सम्मिलित किए गए गुणों के लिए, आपकी प्रॉपर्टी मैपिंग (.hbm.xml) ऐसा दिखेगी:

 <property name="foo" generated="insert"/> 

सम्मिलित होने और अपनी प्रॉपर्टी मैपिंग (.hbm.xml) को अपडेट करने पर उत्पन्न गुणों के लिए ऐसा दिखेगा:

 <property name="foo" generated="always"/> 

दुर्भाग्य से, मैं जेपीए नहीं जानता, इसलिए मुझे नहीं पता कि यह सुविधा जेपीए के जरिए सामने आई है (मुझे शक नहीं है)

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

इस तरह से आप प्रॉपर्टी को डालने और अपडेट स्टेटमेंट में उपयोग किए जाने से अलग कर लेंगे:

 <property name="foo" update="false" insert="false"/> 

दोबारा, मुझे नहीं पता कि क्या जेपीए इन सीतनिद्रा में होना सुविधाओं को उजागर करती है, लेकिन सीतनिद्रा में होना उन्हें समर्थन करता है।

मुझे पता है यह एक बहुत पुराना सवाल है, लेकिन यह सबसे पहले परिणामों पर दिखाया गया है और जेपीए ने सवाल से बहुत कुछ बदल दिया है।

इसे अभी करने का सही तरीका @Generated एनोटेशन के साथ है आप अनुक्रम को परिभाषित कर सकते हैं, उस क्रम में कॉलम में डिफ़ॉल्ट सेट करें और फिर कॉलम को इस रूप में मैप करें:

 @Generated(GenerationTime.INSERT) @Column(name = "column_name", insertable = false) 

एक फॉलोअप के रूप में यहां बताया गया है कि मुझे यह काम कैसे करना है:

 @Override public Long getNextExternalId() { BigDecimal seq = (BigDecimal)((List)em.createNativeQuery("select col_msd_external_id_seq.nextval from dual").getResultList()).get(0); return seq.longValue(); } 

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

मैंने उस मुद्दे को एक कस्टम एनोटेशन शुरू करने के लिए सुलझाया जो सिंकेंस नामक कोई संपत्ति नहीं थी। यह फ़ील्ड के लिए केवल एक मार्कर है जिसे एक वृद्धिशील अनुक्रम से मान निर्दिष्ट किया जाना चाहिए।

 @Retention(RetentionPolicy.RUNTIME) @Target(ElementType.FIELD) public @interface Sequence { } 

इस एनोटेशन का उपयोग करके मैंने अपनी संस्थाओं को चिह्नित किया।

 public class Area extends BaseEntity implements ClientAware, IssuerAware { @Column(name = "areaNumber", updatable = false) @Sequence private Integer areaNumber; .... } 

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

 @Entity @Table(name = "SequenceNumber", uniqueConstraints = { @UniqueConstraint(columnNames = { "className" }) }) public class SequenceNumber { @Id @Column(name = "className", updatable = false) private String className; @Column(name = "nextValue") private Integer nextValue = 1; @Column(name = "incrementValue") private Integer incrementValue = 10; ... some getters and setters .... } 

अंतिम चरण और सबसे कठिन एक प्रीइन्सर्ट लिस्टनर है जो अनुक्रम संख्या असाइन करता है। ध्यान दें कि मैंने बीन कंटेनर के रूप में वसंत का इस्तेमाल किया

 @Component public class SequenceListener implements PreInsertEventListener { private static final long serialVersionUID = 7946581162328559098L; private final static Logger log = Logger.getLogger(SequenceListener.class); @Autowired private SessionFactoryImplementor sessionFactoryImpl; private final Map<String, CacheEntry> cache = new HashMap<>(); @PostConstruct public void selfRegister() { // As you might expect, an EventListenerRegistry is the place with which event listeners are registered // It is a service so we look it up using the service registry final EventListenerRegistry eventListenerRegistry = sessionFactoryImpl.getServiceRegistry().getService(EventListenerRegistry.class); // add the listener to the end of the listener chain eventListenerRegistry.appendListeners(EventType.PRE_INSERT, this); } @Override public boolean onPreInsert(PreInsertEvent p_event) { updateSequenceValue(p_event.getEntity(), p_event.getState(), p_event.getPersister().getPropertyNames()); return false; } private void updateSequenceValue(Object p_entity, Object[] p_state, String[] p_propertyNames) { try { List<Field> fields = ReflectUtil.getFields(p_entity.getClass(), null, Sequence.class); if (!fields.isEmpty()) { if (log.isDebugEnabled()) { log.debug("Intercepted custom sequence entity."); } for (Field field : fields) { Integer value = getSequenceNumber(p_entity.getClass().getName()); field.setAccessible(true); field.set(p_entity, value); setPropertyState(p_state, p_propertyNames, field.getName(), value); if (log.isDebugEnabled()) { LogMF.debug(log, "Set {0} property to {1}.", new Object[] { field, value }); } } } } catch (Exception e) { log.error("Failed to set sequence property.", e); } } private Integer getSequenceNumber(String p_className) { synchronized (cache) { CacheEntry current = cache.get(p_className); // not in cache yet => load from database if ((current == null) || current.isEmpty()) { boolean insert = false; StatelessSession session = sessionFactoryImpl.openStatelessSession(); session.beginTransaction(); SequenceNumber sequenceNumber = (SequenceNumber) session.get(SequenceNumber.class, p_className); // not in database yet => create new sequence if (sequenceNumber == null) { sequenceNumber = new SequenceNumber(); sequenceNumber.setClassName(p_className); insert = true; } current = new CacheEntry(sequenceNumber.getNextValue() + sequenceNumber.getIncrementValue(), sequenceNumber.getNextValue()); cache.put(p_className, current); sequenceNumber.setNextValue(sequenceNumber.getNextValue() + sequenceNumber.getIncrementValue()); if (insert) { session.insert(sequenceNumber); } else { session.update(sequenceNumber); } session.getTransaction().commit(); session.close(); } return current.next(); } } private void setPropertyState(Object[] propertyStates, String[] propertyNames, String propertyName, Object propertyState) { for (int i = 0; i < propertyNames.length; i++) { if (propertyName.equals(propertyNames[i])) { propertyStates[i] = propertyState; return; } } } private static class CacheEntry { private int current; private final int limit; public CacheEntry(final int p_limit, final int p_current) { current = p_current; limit = p_limit; } public Integer next() { return current++; } public boolean isEmpty() { return current >= limit; } } } 

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

उम्मीद है कि यह किसी को मदद करता है

मैं आपके जैसी स्थिति में दौड़ता हूं और मुझे भी कोई गंभीर जवाब नहीं मिल पाया है अगर यह मूल रूप से जेपीए के साथ गैर-आईडी संपत्तियां पैदा करना संभव है या नहीं।

मेरा समाधान यह दृढ़ता से पहले संपत्ति द्वारा सेट करने के लिए मूल जीपीए क्वेरी के साथ अनुक्रम को कॉल करना है।

यह संतोषजनक नहीं है लेकिन यह पल के लिए एक वैकल्पिक हल के रूप में काम करता है।

मारियो

मैंने @PrePersist एनोटेशन का उपयोग करके हाइबरनेट के साथ @PrePersist (या अनुक्रम) की पीढ़ी तय की है:

 @PrePersist public void initializeUUID() { if (uuid == null) { uuid = UUID.randomUUID().toString(); } } 

मैंने सत्र में यह विशिष्ट नोट पाया है 9.1.9 जेपीए विनिर्देश से जनरेटेड वैल्यू एनोटेशन: "[43] पोर्टेबल अनुप्रयोगों को अन्य लगातार क्षेत्रों या प्रॉपर्टी पर जनरेटेड वैल्यू एनोटेशन का उपयोग नहीं करना चाहिए।" तो, मुझे लगता है कि कम से कम जेपीए का उपयोग करके गैर प्राथमिक कुंजी मानों के लिए स्वतः उत्पन्न मूल्य संभव नहीं है।

मैं आपके जैसी स्थिति में हूं (गैर @ आईडी क्षेत्र के लिए जेपीए / सीतनिद्रा में होना अनुक्रम) और मैंने अपने डीबी स्कीमा में एक ट्रिगर तैयार किया जो कि डालने पर एक अद्वितीय अनुक्रम संख्या जोड़ती है। मैं इसे जेपीए / सीतनिद्रा में होना के साथ काम करने के लिए कभी नहीं मिला

"मैं अपनी संपत्ति के मूल्य को उत्पन्न करने के लिए स्वयं हाइबरनेट के अलावा एक ट्रिगर या किसी अन्य चीज का उपयोग नहीं करना चाहता"

उस स्थिति में, यूज़रटाइप के कार्यान्वयन के बारे में कैसे जो आवश्यक मान उत्पन्न करता है, और मेटाडाटा को उस यूज़रटाइप का उपयोग करने के लिए mySequenceVal संपत्ति के हठ के लिए कॉन्फ़िगर करना है?

यह अनुक्रम का उपयोग करने के समान नहीं है अनुक्रम का उपयोग करते समय, आप कुछ भी सम्मिलित या अपडेट नहीं कर रहे हैं आप बस अगले क्रम मान को पुनः प्राप्त कर रहे हैं। ऐसा लगता है कि सीतनिद्रा में होना इसका समर्थन नहीं करता।