سؤال

وأستخدمه JPA مع السبات تحتها، وأواجه صعوبة في الحصول على دمج للعمل، ولكن قبل أن تصف مشاكل تواجهني مع نقابة الصحفيين، اسمحوا لي أن تحدد ما أحاول تحقيقه، فقط في حالة مشاكلي ينبع من وجهة نظري.

ولدي البيانات من على النظام أنني بحاجة إلى مكان في نظام آخر. للقيام بذلك وأنا قراءة البيانات ثم بناء الأجسام ORM جديدة على أساس تلك البيانات، وبعد ذلك تريد أن تستمر ORM الكائنات في قاعدة البيانات. الآن عند قاعدة البيانات فارغة، ويعمل البرنامج من دون قضية، مع (كائن) دعوة بسيطة em.persist. ولكن أريد أن تكون قادرة على تشغيل هذه العملية عند قاعدة البيانات لديها البيانات فيه، إضافة بيانات جديدة وتحديث البيانات القديمة عند الضرورة، وهذا هو المكان الذي أواجه القضايا.

وأفعل فحص بسيط لمعرفة ما إذا كان هذا البند موجود مسبقا في قاعدة البيانات، إذا وجدت أي شيء، وأنا لا تزال قائمة، في حالة وجود سجل، ومحاولة دمج. الذي فشل مع خطأ سجل مكررة؛

ERROR JDBCExceptionReporter - Violation of UNIQUE KEY constraint 'UK-SubStuff-StuffId-SubStuffNumber'. Cannot insert duplicate key in object 'SubStuff'.

ويبدو لي كما الغريب أن الدعوة em.merge () يحاول ادخال بدلا من التحديث (وقد أكدت ذلك من خلال تسجيل SQL).

Hibernate: insert into SubStuff (SubStuffNumber, StuffId, Name, TypeId) values (?, ?, ?, ?)

وأود أن أشير إلى أن أستخدمه الكائنات التي تتالي إلى أشياء فرعية. فشل يحدث على وجوه الفرعي، الأمر الذي يجعل من المنطقي بالنسبة لي كما أتوقع ذلك في محاولة لدمج الكائنات الفرعية أولا.

وأدناه هو قانون بلدي، يرجى عذر الدولة الخام، حاولت توثيق يقترب عدد قليل من الحل هنا.

private void storeData(Collection<Stuff> Stuffs) {

    for (Stuff stuff : Stuffs) {
        //I think this first block can be safely ignored, as I am having no issues with it
        //  Left it in just in case someone more experianced then I sees the root of the issue here.
        Collection<SubStuff> subStuffs = stuff.getSubStuffCollection();
        for (SubStuff s : subStuffs) {
            //Persist SubStuff Type, which DOES NOT cascade,
            //  due to it not having an internal SubStuff collection
            Query q = em.createNamedQuery("SubStuffType.findByType");
            q.setParameter("type", f.getTypeId().getType());
            try {
                SubStuffType sst = (SubStuffType) q.getSingleResult();
                s.setTypeId(sst);
            } catch (NoResultException ex) {
                if (logger.isDebugEnabled()) logger.debug("SubStuff Type not found, persisting");
                em.persist(s.getTypeId());
            }
        }

        if (em.find(Stuff.class, stuff.getId()) == null) {
            //Persist on Stuffs will cascade to SubStuffs
            em.persist(stuff);
        } else {
            //  Failing to merge SubStuff, tries to insert duplicate
            //  Merge SubStuff first
            // The block below is my attempt to merge the SubStuff Collection before merging Stuff,
            //  it creates the same isuse as a straight merge of Stuff.
            Collection<SubStuff> mergedSubStuffs = new ArrayList<SubStuff>(SubStuffs.size());
            for (SubStuff s : SubStuffs) {
                Query q = em.createNamedQuery("SubStuff.findBySubStuffNumberStuffId");
                q.setParameter("SubStuffNumber", s.getSubStuffNumber());
                q.setParameter("StuffId", stuff.getId());
                try {
                    SubStuff subStuff = (SubStuff) q.getSingleResult();
        // -----> Merge fails, with an duplicate insert error
                    SubStuff mergedSubStuff = em.merge(s);
                    mergedSubStuffs.add(mergedSubStuff);
                } catch (NoResultException ex) {
                    throw ex;
                }
            }
            stuff.setSubStuffCollection(mergedSubStuffs);

        // -----> This will fails with same error as above, if I remove the attempt
            //  to merge the sub objects
            em.merge(stuff);
        }
    }
}

وإذا كان أي شخص من ذوي الخبرة JPA يستطيع مساعدتي وسأكون ممتنا حقا. وdifferances بين saveOrUpdate السبات في () ودمج نقابة الصحفيين الأردنيين () يبذلون قصارى جهدهم الواضح لي، ولكن على الرغم من قراءة العديد من المقالات حول دمج EnityManger، وأنا لا تزال لا يمكن التفاف رأسي حول ما يجري هنا.

وشكرا على وقتك.

هل كانت مفيدة؟

المحلول

لقد ضربت لعنة ستاكوفيرفلوو مرة أخرى. بعد أن عمل على حل هذه المشكلة لمدة يوم واحد قررت أن الرد على هذا السؤال، في غضون 20 دقيقة كان لي لحظة اكتشاف وحلها. جزئيا لأنني كنت قد أوضح أفكاري كافية لنشر السؤال. في التفكير في ما هي المعلومات التي قد تكون وثيقة الصلة السؤال أدركت أن بلادي السيارات لدت مفاتيحها إلقاء اللوم على (أو بلدي بشكل صحيح، يا غبي غير مناولة منهم على دمج).

وبلدي المسألة هي أن SubStuff (مخطط أسوأ بديل التسمية، آسف لذلك) لديه المفتاح الأساسي الاصطناعي يتم إنشاؤه تلقائيا. لذلك عندما دمج ما يلزم القيام به؛

SubStuff subStuff = (SubStuff) q.getSingleResult();
//++++++++
s.setId(subStuff.getId());
//++++++++

//The following code can be removed.
//--- SubStuff mergedSubStuff = em.merge(f);
//--- mergedSubStuffs.add(mergedSubStuff);

وهذا يضع المفتاح الأساسي إلى الصف الذي موجود بالفعل في قاعدة البيانات، وبناء على الاختبارات الأولية يبدو أن تعمل بشكل جيد.

والدعوة إلى دمج يمكن تبسيط وصولا الى مجرد الدعوة إلى em.merge (الاشياء) والتي من شأنها تتالي الكائنات substuff وجمع mergedsubstuff يمكن إزالتها جميعا ونحن لم تعد تفعل دمج داخل تلك الحلقة.

والشكر لمن تقرأ من خلال سؤالي طويل للغاية، ونأمل سؤالي تكون مفيدة لشخص ما في المستقبل.

نصائح أخرى

والمشكلة هي مع الزوجين التالية من خطوط:

Collection<SubStuff> mergedSubStuffs = new ArrayList<SubStuff>(SubStuffs.size());
...
stuff.setSubStuffCollection(mergedSubStuffs);

والنقابة ستدرس مجموعة جديدة مجموعة جديدة كاملة من حيث الكيانات الفرعية وسيتم إدراج دائما على هذا النحو. الاستمرار في العمل مع المجموعة الأصلية من SubStuff داخل كيان الاشياء وسوف يكون على ما يرام.

مرخصة بموجب: CC-BY-SA مع الإسناد
لا تنتمي إلى StackOverflow
scroll top