السبات (JPA) كيفية إجراء استعلام حريص وتحميل جميع الكائنات الفرعية

StackOverflow https://stackoverflow.com/questions/70992

  •  09-06-2019
  •  | 
  •  

سؤال

تتعلق بي سؤال سابق, ، أريد التأكد من تحميل جميع الكائنات الفرعية لأن لدي سلاسل رسائل متعددة قد تحتاج إلى الوصول إلى البيانات (وبالتالي تجنب استثناءات التحميل البطيئة).أتفهم أن طريقة القيام بذلك هي استخدام الكلمة الأساسية "جلب" في الاستعلام (EJB QL).مثله:

select distinct o from Order o left join fetch o.orderLines

بافتراض نموذج مع Order الطبقة التي لديها مجموعة من OrderLines فيه.

سؤالي هو أنه يبدو أن الكلمة الأساسية "المميزة" مطلوبة وإلا فإنني سأعود Order لكل OrderLine.هل اقوم بالعمل الصحيح؟

وربما الأهم من ذلك، هل هناك طريقة لسحب جميع الأشياء الصغيرة، بغض النظر عن مدى عمقها؟لدينا حوالي 10-15 فصلًا وبالنسبة للخادم، سنحتاج إلى تحميل كل شيء...كنت أتجنب استخدام FetchType.EAGER لأن هذا يعني أنها حريصة دائمًا، وعلى وجه الخصوص، تقوم الواجهة الأمامية للويب بتحميل كل شيء - ولكن ربما يكون هذا هو الطريق الذي يجب اتباعه - هل هذا ما تفعله؟يبدو أنني أتذكر أننا جربنا ذلك من قبل ثم حصلنا على صفحات ويب بطيئة جدًا - ولكن ربما يعني ذلك أننا يجب أن نستخدم ذاكرة تخزين مؤقت من المستوى الثاني؟

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

المحلول

يعد تغيير التعليق التوضيحي فكرة سيئة للمنظمة البحرية الدولية.لأنه لا يمكن تغييره إلى كسول في وقت التشغيل.من الأفضل أن تجعل كل شيء كسولًا وجلبه حسب الحاجة.

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

نصائح أخرى

لست متأكدًا من استخدام الكلمة الأساسية للجلب في EJBQL الخاص بك، ربما يتم الخلط بينها وبين التعليق التوضيحي...

هل حاولت إضافة خاصية FetchType إلى سمة علاقتك؟

@OneToMany(fetch=FetchType.EAGER)؟

يرى:

http://java.sun.com/javaee/5/docs/api/javax/persistence/FetchType.html http://www.jroller.com/eyallupu/entry/hibernate_exception_simultaneously_fetch_multiple

هل حاولت استخدام محول النتيجة؟إذا كنت تستخدم استعلامات المعايير، فيمكنك تطبيق محول النتائج (على الرغم من أن هناك بعض المشاكل مع ترقيم الصفحات ومحول النتيجة):

Criteria c = ((Session)em.getDelegate()).createCriteria(Order.class);
c.setResultTransformer(Criteria.DISTINCT_ROOT_ENTITY);
c.list();

ال em.getDelegate() هو اختراق لا يعمل إلا إذا كنت تستخدم السبات.

ربما الأهم من ذلك ، هل هناك طريقة لسحب جميع الأشياء الفرعية ، بغض النظر عن مدى عمقها؟لدينا حوالي 10-15 فئة ولخادم سنحتاج إلى كل شيء محمّل ...كنت أتجنب استخدام fetchtype.eager لأن هذا يعني أنه حريص دائمًا ، ولا سيما أن الواجهة الأمامية على شبكة الإنترنت تعمل على تحميل كل شيء - ولكن ربما يكون هذا هو السبيل للذهاب - هل هذا ما تفعله؟يبدو أنني أتذكرنا أن نحاول ذلك من قبل ، ثم الحصول على صفحات ويب بطيئة حقًا - ولكن ربما هذا يعني أننا يجب أن نستخدم ذاكرة التخزين المؤقت من المستوى الثاني؟

إذا كنت لا تزال مهتمًا، فقد أجبت على سؤال مماثل في هذا الموضوع كيفية تسلسل مجموعات السبات.

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

قد تتمكن من القيام بشيء كهذا باستخدام استعلام معايير (منفصل)، وتعيين وضع الجلب.على سبيل المثال،

Session s = ((HibernateEntityManager) em).getSession().getSessionFactory().openSession();
DetachedCriteria dc = DetachedCriteria.forClass(MyEntity.class).add(Expression.idEq(id));
dc.setFetchMode("innerTable", FetchMode.JOIN);
Criteria c = dc.getExecutableCriteria(s);
MyEntity a = (MyEntity)c.uniqueResult();

لن يعمل ذلك إلا مع علاقات ManyToOne وربما يكون @ManyToOne(fetch=FetchType.EAGER) مناسبًا لهم.

لا يُنصح بجلب أكثر من علاقة OneToMany بفارغ الصبر و/أو لا يعمل كما يمكنك أن تقرأ في الرابط الذي نشره جيريمي.مجرد التفكير في عبارة SQL التي ستكون ضرورية للقيام بمثل هذا الجلب ...

ما قمت به هو إعادة بناء الكود للاحتفاظ بخريطة الكائنات لمديري الكيانات وفي كل مرة أحتاج إلى التحديث، أغلق مدير الكيان القديم للكائن وافتح واحدًا جديدًا.لقد استخدمت الاستعلام أعلاه بدون أحضر نظرًا لأن ذلك يعد أمرًا عميقًا للغاية بالنسبة لاحتياجاتي - فمجرد القيام بربط عادي يؤدي إلى سحب OrderLines - أحضر يجعلها تذهب أعمق.

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

لقد قمت أيضًا بإعادة عمل الأشياء بحيث يكون عمل قاعدة البيانات في الموضوع الرئيسي ولديه مدير الكيان.

كريس

إذا كانت المشكلة تتعلق فقط بـ LazyInitializationExceptions، فيمكنك تجنب ذلك عن طريق إضافة OpenSessionInViewFilter.
سيسمح هذا بتحميل الكائنات في العرض، لكنه لن يساعد في حل مشكلة السرعة.

     <filter>
        <filter-name>hibernateFilter</filter-name>
        <filter-class> org.springframework.orm.hibernate3.support.OpenSessionInViewFilter
        </filter-class>
    </filter>
    <filter-mapping>
        <filter-name>hibernateFilter</filter-name>
        <url-pattern>/*</url-pattern>
    </filter-mapping>
مرخصة بموجب: CC-BY-SA مع الإسناد
لا تنتمي إلى StackOverflow
scroll top