jpa

2012-10-05 10 views
5

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

@Id 
@Basic(optional = false) 
@Column(name = "ID", nullable = false) 
@GeneratedValue(strategy = GenerationType.SEQUENCE, generator = "woTypeSeq") 
private Long id; 

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

मुझे लगता है कि

if(entity.getCode()==null) { 
    entity.setCode(entity.getId); 
    jpaDao.saveOrUpdate(entity); 
} 
+1

आप @GeneratedValue से बचने, जनरेटर खुद का उपयोग मूल्य प्राप्त करने और "मैन्युअल" संस्था के लिए यह सेट कर सकते हैं – SJuan76

+0

मैं न यहाँ सरल कार्यान्वयन है इसे मैन्युअल रूप से इकाई में सेट करना चाहते हैं। अगर मुझे ऑरैकल से आईडी के लिए अगला मान मिलता है और मैं इसे नई इकाई की आईडी पर सेट करता हूं, तो क्या यह तर्कसंगत है? – mstzn

उत्तर

5

लंबे बारे में शोध करने के बाद अंत में, मुझे एक समाधान मिला।

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

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

public class CustomGenerator extends IdentityGenerator implements Configurable { 

    private IdentifierGenerator defaultGenerator; 

    public Serializable generate(SessionImplementor session, Object object) throws HibernateException { 
     Long idValue = (Long)defaultGenerator.generate(session, object); 
     //idValue will be assigned your entity id 
     return idValue; 
    } 

    @Override 
    public void configure(Type type, Properties params, Dialect d) throws MappingException { 
     DefaultIdentifierGeneratorFactory dd = new DefaultIdentifierGeneratorFactory(); 
     dd.setDialect(d); 
     defaultGenerator = dd.createIdentifierGenerator("sequence", type, params); 
    } 
} 

आईडी क्षेत्र के लिए CustomGenerator का उपयोग करना::

@Id 
@Basic(optional = false) 
@Column(name = "ID", nullable = false) 
@GenericGenerator(name = "seq_id", strategy = "com.yoncabt.abys.core.listener.CustomGenerator", parameters = { @Parameter(name = "sequence", value = "II_FIRM_DOC_PRM_SEQ") }) 
@GeneratedValue(generator = "seq_id") 
private Long id; 
8
एक @GeneratedValue प्रकार id आप (वास्तव में यह लिखने से पहले) पहले से है कि मूल्य में पता नहीं कर सकते हैं

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

MyEntiry myEnt = new MyEntity(); //the id field is null now 
entityManager.persist(myEnt);//the id field is populated in myEnt now 
Long id = myEnt.getId(); 

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

टिप्पणी के अनुसार अद्यतन

आप रोकना और बाद ही उसे सहेजा और/या अद्यतन किया जाता है संस्था के लिए कुछ करने के लिए, आप (आप जेपीए संस्करण 2 का उपयोग कर रहे हैं) जेपीए जीवनचक्र श्रोताओं का उपयोग कर सकते हैं: Handling JPA lifecycle event using listeners and callbacks

मूल रूप से आप अपने सेम में एक validate() विधि बना सकते हैं, @PrePersist और @PreUpdate साथ उस पर टिप्पणी और

2 टिप्पणी प्रति अद्यतन (यदि कोड खाली सेट यह आईडी के मूल्य के लिए है) उस में सत्यापन करना

हां, मैंने ईमानदारी से अभी सोचा है कि अगर आईडी स्वचालित रूप से जेनरेट की गई है, तो यह प्री-पर्सिस्ट इवेंट के बाद आबादी हो सकती है, जैसे कि जब आपका प्री-पर्सिस्ट कोड निष्पादित होता है तब भी आप नहीं जानते कि आईडी क्या है (आप यह भी ध्यान दे सकते हैं कि उदाहरण के लिए आप आईडी से लिंक नहीं करते हैं लेकिन स्वचालित रूप से सेट नहीं होते हैं)। इस मामले में आप क्या कर सकते हैं अपनी इकाई में एक बुलियन फ़ील्ड जोड़ें (@Transient के साथ एनोटेटेड है, इसलिए यह जारी नहीं रहेगा) जिसे isCodeEmpty कहा जाता है (जो विशेष रूप से प्रारंभ नहीं होने पर डिफ़ॉल्ट रूप से गलत है)। फिर आपके @PrePersist एनोटेटेड विधि में आप जांचते हैं कि कोड फ़ील्ड का मान खाली है या नहीं, और यदि ऐसा है, तो बूलियन को सत्य पर सेट करें। तो फिर तुम (आईडी क्षेत्र की स्थापना को छोड़ कर) ऐसी है कि आपके setId(...) विधि refactor यह इस बूलियन की जाँच करेगा, और अगर सच सेट आईडी क्षेत्र की है कि कोड फ़ील्ड का मान:

public class YourEntity { 

@Transient 
private boolean isCodeEmpty; 

public void setId(Whatever id) { 
this.id = id; 
if(isCodeEmpty) { 
    this.code = id; 
    //if necessary: 
    //this.isCodeEmpty = false; 
} 
} 

@PrePersist 
public void validate() { 
if(code == null || code.isEmpty()) { 
    isCodeEmpty = true; 
} 

} 


} 
+0

उत्तर देने के लिए धन्यवाद। मैंने अपना प्रश्न अपडेट किया। क्या आप इसे देख सकते हैं? – mstzn

+0

मैंने इकाई श्रोता की कोशिश की है। लेकिन प्रीपेरिस्ट आईडी मान में शून्य है। मुझे नहीं पता कि यह शून्य क्यों है। मैं इस तरह लागू करता हूं = http://www.java2s.com/Tutorial/Java/0355__JPA/EntityListenersPrePersist.htm क्या आपके पास है सुझाव या विचार? बहुत बहुत धन्यवाद – mstzn

+1

आपका विचार उत्कृष्ट है लेकिन प्रीपेर्सिस्ट setId() विधि काम नहीं कर रहा है। मैंने जो कहा वह मैंने किया। मैं इसे डीबग कर रहा हूं, लेकिन setId विधि निष्पादित नहीं की गई है और कोड फ़ील्ड सेट नहीं है। प्रेरक काम कर रहा है। – mstzn