2012-06-14 12 views
17

मैं निम्नलिखित इकाई वर्गों के साथ एक द्विदिश एक-से-कई संबंध हैं:जेपीए: इकाई बनी रहती है और विलय सोपानी बच्चे संस्थाओं

0 या 1 ग्राहक < -> 0 या अधिक उत्पाद आदेश

क्लाइंट इकाई को बनाए रखने पर मैं संबंधित उत्पाद ऑर्डर इकाइयों को भी जारी रखना चाहता हूं (क्योंकि "मूल" क्लाइंट को उनकी विदेशी कुंजी अपडेट हो सकती है)।

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

  1. उत्पाद आदेश '1' बनाया है और एक समान होती है। ठीक काम करता है।
  2. क्लाइंट '2' बनाया गया है और उत्पाद ऑर्डर '1' को इसके उत्पाद ऑर्डर सूची में जोड़ा गया है। फिर यह जारी है। काम नहीं करता।

मैंने कई apporaches की कोशिश की, लेकिन उनमें से कोई भी अपेक्षित परिणाम दिखाया। नीचे उन परिणामों को देखें। मैंने यहां सभी संबंधित प्रश्न पढ़े, लेकिन उन्होंने मेरी मदद नहीं की। मैं ग्लासफ़िश 3.1.2 पर अपाचे डर्बी (जावाडीबी) इन-मेमोरी डीबी पर लेनदेन प्रकार के रूप में एक्लिप्ससेंक 2.3.0, शुद्ध जेपीए 2.0 एनोटेशन और जेटीए का उपयोग करता हूं। इकाई संबंध एक जेएसएफ जीयूआई द्वारा प्रबंधित किया जाता है। ऑब्जेक्ट लेवल रिलेशनशिप मैनेजमेंट काम करता है (लगातार रहने के अलावा), मैंने इसे जुनीट परीक्षणों के साथ परीक्षण किया।

दृष्टिकोण 1) "डिफ़ॉल्ट" (NetBeans वर्ग टेम्प्लेट के आधार पर)

ग्राहक:

@Entity 
public class Client implements Serializable, ParentEntity { 
    private static final long serialVersionUID = 1L; 
    @Id 
    @GeneratedValue(strategy = GenerationType.AUTO) 
    private Long id; 

    @OneToMany(mappedBy = "client", cascade={CascadeType.PERSIST, CascadeType.MERGE, CascadeType.REFRESH}, 
      fetch= FetchType.LAZY) 
    private List<ProductOrder> orders = new ArrayList<>(); 

    // other fields, getters and setters 
} 

ProductOrder:

@Entity 
public class ProductOrder implements Serializable, ChildEntity { 
    private static final long serialVersionUID = 1L; 

    @Id 
    @GeneratedValue(strategy = GenerationType.AUTO) 
    private Long id; 

    @ManyToOne // owning side 
    private Client client; 

    // other fields, getters and setters 
} 

जेनेरिक हठ फसाड:

// Called when pressing "save" on the "create new..." JSF page 
public void create(T entity) { 
    getEntityManager().persist(entity); 
} 

// Called when pressing "save" on the "edit..." JSF page 
public void edit(T entity) { 
    getEntityManager().merge(entity); 
} 

परिणाम:

चेतावनी:: एक सिस्टम अपवाद EJB ClientFacade पद्धति पर एक मंगलाचरण के दौरान हुई सार्वजनिक शून्य javaee6test.beans.AbstractFacade.create (java.lang

(बनाने) इस अपवाद immediatly फेंकता .Object) javax.ejb.EJBException: लेन-देन निरस्त किया गया ...

की वजह से: javax.transaction.RollbackException: लेन-देन रोलबैक के लिए चिह्नित किया। ...

की वजह से: अपवाद [EclipseLink-4002] (ग्रहण हठ सेवाएं - 2.3.0.v20110604-r9504): org.eclipse.persistence.exceptions.DatabaseException आंतरिक अपवाद: java.sql। SQLIntegrityConstraintViolationException: राज्य-वस्तु को निरस्त कर दिया गया था क्योंकि इससे 'PRODUCTORDER' पर परिभाषित 'SQL120513133540930' द्वारा एक अद्वितीय या प्राथमिक कुंजी बाधा या अद्वितीय सूचकांक में डुप्लिकेट कुंजी मान उत्पन्न होता।त्रुटि कोड: -1 कॉल: उत्पादक में प्रवेश (आईडी, CLIENT_ID) मूल्य (?,?) बाइंड => [2 पैरामीटर बाध्य] क्वेरी: InsertObjectQuery (javaee6test.model.ProductOrder [id = 1]) ...

की वजह से: java.sql.SQLIntegrityConstraintViolationException: बयान निरस्त कर दिया गया है क्योंकि यह एक अद्वितीय या प्राथमिक कुंजी बाधा या अद्वितीय सूचकांक 'SQL120513133540930' 'प्रो पर परिभाषित द्वारा की पहचान में एक नकली चाबी मूल्य उत्पन्न कर DUCTORDER '। ...

की वजह से: org.apache.derby.client.am.SqlException: बयान निरस्त कर दिया गया होना कारण यह एक अद्वितीय या प्राथमिक कुंजी चोर-straint में एक नकली चाबी मूल्य उत्पन्न कर या 'PRODUCTOR-DER' पर परिभाषित 'SQL120513133540930' द्वारा पहचाना गया अद्वितीय सूचकांक।

मुझे यह अपवाद नहीं समझा। संपादित करें() ठीक काम करता है। लेकिन मैं अपने निर्माण समय पर किसी ग्राहक को उत्पाद आदेश जोड़ना चाहता हूं, इसलिए यह अपर्याप्त है।

दृष्टिकोण 2) विलय() केवल

जेनेरिक हठ फसाड में परिवर्तन:

// Called when pressing "save" on the "create new..." JSF page 
public void create(T entity) { 
    getEntityManager().merge(entity); 
} 

// Called when pressing "save" on the "edit..." JSF page 
public void edit(T entity) { 
    getEntityManager().merge(entity); 
} 

परिणाम:

पर (बनाने), EclipseLink लॉगिंग उत्पादन का कहना है:

ठीक है: ग्राहक में आईडी (आईडी, NAME, ADDRESS_ID) मूल्य (?, ?,?) बाइंड => [3 पैरामीटर बाध्य]

लेकिन उत्पाद आदेश तालिका पर कोई "अद्यतन" नहीं। इस प्रकार, संबंध स्थापित नहीं है। फिर, संपादित करें(), दूसरी ओर, ठीक काम करता है।

apporach 3) आईडी GenerationType.IDENTITY दोनों इकाई प्रकार दोनों क्लाइंट और उत्पाद आदेश वर्ग के लिए

परिवर्तन पर:

... 
@Id 
@GeneratedValue(strategy = GenerationType.IDENTITY) 
private Long id; 
... 

परिणाम:

पर (बनाने), EclipseLink लॉगिंग आउटपुट कहता है:

ठीक है: INSERT I Nto ग्राहक (नाम, ADDRESS_ID) मान बाँध => [2 मापदंडों बाध्य]

ललित (,?): मान IDENTITY_VAL_LOCAL()

ललित: PRODUCTORDER (ORDERDATE, CLIENT_ID) मान में डालें (? ,?) बाँध => [2 मापदंडों बाध्य]

ललित: मान IDENTITY_VAL_LOCAL()

इस प्रकार के बजाय ग्राहक की सूची में जोड़ा उत्पाद क्रम में एक रिश्ता estabilshing की, एक नया prodcut आदेश इकाई बनाई गई है और जारी (!) और उस इकाई के साथ संबंध estabilshed है। यहां वही, संपादित करें() ठीक काम करता है।

apporach 4) दृष्टिकोण (2) और (3) संयुक्त

परिणाम: दृष्टिकोण के रूप में एक ही (2)।

मेरा प्रश्न है: क्या ऊपर वर्णित परिदृश्य को समझने का कोई तरीका है? यह कैसे पहुंचा जा सकता है? मैं जेपीए (कोई विक्रेता-विशिष्ट समाधान) के साथ रहना चाहता हूं।

उत्तर

0

अपने उत्पाद ऑर्डर इकाई में @Joincolumn एनोटेशन का उपयोग करें, कृपया नीचे देखें।

@Entity 
    public class ProductOrder implements Serializable, ChildEntity { 
    private static final long serialVersionUID = 1L; 

    @Id 
    @GeneratedValue(strategy = GenerationType.AUTO) 
    private Long id; 

    @ManyToOne // owning side 
    @JoinColumn(name = "PRODUCTORDER_ID", referencedColumnName = "ID") 
    //write your database column names into name and referencedColumnName attributes. 
    private Client client; 

    // other fields, getters and setters 
    } 
+1

नहीं, यह काम नहीं करता है। यह वास्तव में कुछ भी नहीं बदलता है। मैंने इसे '@ जॉइन कॉलम (नाम = "CLIENT_ID", संदर्भित कॉलमनाम = "आईडी") 'के साथ करने की कोशिश की, लेकिन यह काम नहीं किया। – SputNick

0

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

लगातार काम नहीं करता है, क्योंकि जारी रखने की आवश्यकता है कि निरंतरता निरंतर संदर्भ के लिए सही हो, यानी पृथक वस्तुओं का संदर्भ न दें, इसे प्रबंधित वस्तुओं का संदर्भ देना चाहिए।

आपकी समस्या आप वस्तुओं को अलग करने से आती है। यदि आपने वस्तुओं को अलग नहीं किया है, तो आपके पास एक ही समस्या नहीं होगी। आम तौर पर जेपीए में आप एक EntityManager बनायेंगे, अपनी ऑब्जेक्ट ढूंढें/पूछेंगे, उन्हें संपादित/जारी रखें, कॉल प्रतिबद्ध करें। कोई विलय की आवश्यकता नहीं है।

+6

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

+0

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

7

हाय मैं एक ही समस्या आज था, मैं इस ईमेल के साथ openJPA मेलिंग सूची के लिए पूछना:

हाय। मुझे एक ही इकाई में एक संदर्भ डालने और अद्यतन करने में समस्या है।

मैं एक नई ऑब्जेक्ट (परीक्षा) डालने की कोशिश कर रहा हूं जिसमें किसी अन्य ऑब्जेक्ट (व्यक्ति) का संदर्भ है और साथ ही मैं व्यक्ति ऑब्जेक्ट की विशेषता (जन्मदिन) को अपडेट करना चाहता हूं। अपडेट कभी नहीं होता है हालांकि मैं सभी को कैस्केड टाइप टाइप करता हूं। यह काम करने का एकमात्र तरीका एक सतत काम कर रहा है और उसके बाद एक विलय ऑपरेशन। क्या यह सामान्य है? क्या मुझे कुछ बदलना है ??

मुझे व्यक्ति ऑब्जेक्ट में विलय का उपयोग करके "मैन्युअल अपडेट" के विचार को पसंद नहीं है क्योंकि मुझे नहीं पता कि उपयोगकर्ता कितनी ऑब्जेक्ट्स (परीक्षा का बच्चा ऑब्जेक्ट) उपयोगकर्ता अपडेट करना चाहता है।

संस्थाओं:

public class Exam{ 
    @ManyToOne(cascade= CascadeType.ALL) 
    @JoinColumn(name = "person_id") 
    public Person person; 
...... 
} 

public class Person{ 
    private Date birthDate; 
    @OneToMany(mappedBy = "person") 
    private List<Exam> exams 
....... 
} 

public class SomeClass{ 
    public void someMethod(){ 
     exam = new Exam() 
     person.setBirthDate(new Date()); 
     exam.setPerson(person); 
     someEJB.saveExam(exam); 
    } 
} 

public class someEJB(){ 

    public void saveExam(Exam exam){ 
     ejbContext.getUserTransaction().begin(); 
     em.persist(exam); 
     //THIS WORKS 
     em.merge(exam.getPerson()); 
     ejbContext.getUserTransaction().commit();  
    } 

} 

मैं हर बच्चे को वस्तु के लिए मर्ज विधि का उपयोग किया है?

और जवाब यह था:

ऐसा लगता है कि आपकी समस्या की तरह है कि परीक्षा नया है, फिर भी व्यक्ति मौजूदा है और जब व्यापक जारी रहती है आपरेशन मौजूदा इकाई को नजरअंदाज कर दिया जाता है। मेरा मानना ​​है कि यह उम्मीद के रूप में काम कर रहा है।

जब तक आपके रिश्तों को कैस्केड टाइप टाइप पर सेट किया जाता है, तो आप हमेशा अपने em.persist (परीक्षा) को बदल सकते हैं; em.merge (परीक्षा) के लिए; यह की नई परीक्षा को बनाए रखने का ख्याल रखेगा, और यह मर्ज कॉल को व्यक्ति को भी कैस्केड करेगा।

धन्यवाद, रिक


मुझे आशा है कि यह आप कर सकते हैं।

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