سؤال

لست متأكدًا من كيفية وصف هذه المشكلة ، لذلك أعتقد أن مثالًا هو أفضل طريقة لطرح سؤالي:

لدي جدولين مع وجود علاقة anmaltomany:

السائقين <-> licenceclass

LicenceClass هي أشياء مثل "Car" و "Motorbike" و "Medium Rigid".

باستخدام معايير السبات ، كيف يمكنني العثور على جميع التراخيص التي تحتوي على كل من "السيارة" و "الدراجات النارية"؟

تحديث 12/11/2008 لقد اكتشفت أنه يمكن تحقيق ذلك بسهولة باستخدام النتيجة المخصصة. ومع ذلك ، فإن المشكلة هي أن محول النتائج يتم تطبيقه فقط بعد أن يعيد الاستعلام نتائجه ، فإنه لا يصبح في الواقع جزءًا من SQL. لذلك أعتقد أن سؤالي هو الآن "هل يمكنك فعل ما وصفته في البداية في SQL - وهل هناك معايير السبات التناظرية؟"

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

المحلول

إليكم كيف حققتها أخيرًا باستخدام HQL:

public List<DriversLicence> findDriversLicencesWith(List<LicenceClass> licenceClasses) {
    String hqlString = "select dl from DriversLicenceImpl dl where 1=1 ";
    for (int i = 0; i < licenceClasses.size(); i++) {
        hqlString += " and :licenceClass" + i + " = some elements(dl.licenceClasses)";
    }

    Query query = getSession().createQuery(hqlString);
    for (int i = 0; i < licenceClasses.size(); i++) {
        query.setParameter("licenceClass" + i, licenceClasses.get(i));
    }
    return query.list();
}

أو باستخدام معايير السبات مع sqlrestriction:

for (LicenceClass licenceClass : licenceClasses) {               
    criteria.add(Restrictions.sqlRestriction("? = some(select " + LicenceClass.PRIMARY_KEY + " from " +
                    LICENCE_CLASS_JOIN_TABLE + "  where {alias}." +
                    DriversLicence.PRIMARY_KEY + " = " + DriversLicence.PRIMARY_KEY + ")",
                    licenceClass.getId(), Hibernate.LONG));
}

LICENCE_CLASS_JOIN_TABLE هو اسم الجدول الذي ينشئه السبات لدعم العلاقة بين العديد من السائقين و licenceclass.

نصائح أخرى

لا يزال بإمكانك استخدام ترميز DOT للعمل عبر العلاقات. على سبيل المثال ، على افتراض أن لديك سائقة.

session.createCriteria(DriversLicence.class)
   .add(Expression.or(
     Expression.eq("licenceClass.type", "Car"),
     Expression.eq("licenceClass.type", "Motorbike")
   )
).list();

رغم ذلك ، أنا ببساطة أتجنب استخدام المعايير في هذه الحالة لأنه ليس استعلام ديناميكي ، ولكن بدلاً من ذلك استخدم:

session.createQuery("from DriversLicence where licenceClass.type in (:types)")
  .setParameterList("types", myListOfTypes)
  .list();

لقد واجهت مشكلة مماثلة ولكن تم إصلاحها باستخدام HQL ، لدي فئة "مؤسسة" مرتبطة بـ "المستخدم" الفئة وأيضًا فيما يتعلق بـ "دور" الفئة ، فإنهم يتنقلون الكثير من العلاقات ، عندما أحتاج إلى جميع الشركات ذات الصلة لمستخدم معين أقوم بما يلي ؛

Select e from Enterprise As e inner join e.Users As u inner join u.Roles As r 
Where u.UserCode=?

أفترض أنه في حالتك يجب أن تفعل شيئًا مثل ؛

Select dl from LicenceClass As l inner join l.DriversLicences As dl
Where 
l.LicenseClass.Name = ? OR 
l.LicenseClass.Name=? OR 
l.LicenseClass.Name=?

أتمنى أن يساعد ذلك.

خيار آخر هو انضمام السلسلة (انضم واحد لكل LICENSECLASS). لقد استخدمت المعايير باني وتنبؤات مثل هذا

 List<Predicate> predicates = new ArrayList<>();
 for(Integer lcId : licenceClassIdList) {
     SetJoin<DriversLicence, LicenceClass> dlClasses = dlRoot.join(DriversLicence_.licenceClasses);
     predicates.add(builder.equal(dlClasses.get(LicenseClass_.id), lcId));
 }
 Predicate predicate = builder.and(predicates.toArray(new Predicate[predicates.size()]));

إشعار dlroot هو كائن فئة الجذر ويمكنك الحصول عليه من فئة المعايير. ناتج عن ما تبحث عنه ...

'I don't think this going to work. I want to find all licences that have both "Car" and "Motorbike" '

User Expression.and(....) instead of Expression.or(....) in the snippet provided by Nick

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