سؤال

ما البدائل لا بد من تنفيذ استعلام توحيد استخدام السبات?أعلم أن السبات لا يدعم الاتحاد الاستفسارات في هذه اللحظة, الآن فقط أرى أن جعل الاتحاد هو استخدام طريقة عرض جدول.

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

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

المحلول

واستخدام VIEW. الطبقات نفسها يمكن تعيين لمختلف الجداول / المناظر باستخدام اسم الكيان، لذلك سوف لا حتى لدينا الكثير من الازدواجية. يجري هناك، وفعلت ذلك، يعمل موافق.

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

نصائح أخرى

هل يمكن استخدام id in (select id from ...) or id in (select id from ...)

على سبيل المثالبدلا من غير العامل

from Person p where p.name="Joe"
union
from Person p join p.children c where c.name="Joe"

هل يمكن أن تفعل

from Person p 
  where p.id in (select p1.id from Person p1 where p1.name="Joe") 
    or p.id in (select p2.id from Person p2 join p2.children c where c.name="Joe");

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

// use set for uniqueness
Set<Person> people = new HashSet<Person>((List<Person>) query1.list());
people.addAll((List<Person>) query2.list());
return new ArrayList<Person>(people);

فإنه غالبا ما يكون من الأفضل أن تفعل اثنين من استعلامات بسيطة من مجمع واحد.

تحرير:

على سبيل المثال, هنا هو شرح الناتج عن الخلية الاستعلام من subselect الحل:

mysql> explain 
  select p.* from PERSON p 
    where p.id in (select p1.id from PERSON p1 where p1.name = "Joe") 
      or p.id in (select p2.id from PERSON p2 
        join CHILDREN c on p2.id = c.parent where c.name="Joe") \G
*************************** 1. row ***************************
           id: 1
  select_type: PRIMARY
        table: a
         type: ALL
possible_keys: NULL
          key: NULL
      key_len: NULL
          ref: NULL
         rows: 247554
        Extra: Using where
*************************** 2. row ***************************
           id: 3
  select_type: DEPENDENT SUBQUERY
        table: NULL
         type: NULL
possible_keys: NULL
          key: NULL
      key_len: NULL
          ref: NULL
         rows: NULL
        Extra: Impossible WHERE noticed after reading const tables
*************************** 3. row ***************************
           id: 2
  select_type: DEPENDENT SUBQUERY
        table: a1
         type: unique_subquery
possible_keys: PRIMARY,name,sortname
          key: PRIMARY
      key_len: 4
          ref: func
         rows: 1
        Extra: Using where
3 rows in set (0.00 sec)

والأهم من ذلك 1.صف لا يستخدم أي مؤشر وترى 200+ الصفوف.سيئة!تنفيذ هذا الاستعلام أخذت 0.7 s wheres كل الاستعلامات الفرعية في ميلي ثانية.

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

لدي حل واحد الحرجة السيناريو (الذي أنا ناضلت كثيرا )مع الاتحاد في HQL .

على سبيل المثالبدلا من لا يعمل :-

select i , j from A a  , (select i , j from B union select i , j from C) d where a.i = d.i 

أو

select i , j from A a  JOIN (select i , j from B union select i , j from C) d on a.i = d.i 

هل يمكن أن تفعل في السبات HQL ->

Query q1 =session.createQuery(select i , j from A a JOIN B b on a.i = b.i)
List l1 = q1.list();

Query q2 = session.createQuery(select i , j from A a JOIN C b on a.i = b.i)
List l2 = q2.list();

ثم ش يمكن إضافة قائمة ->

l1.addAll(l2);

وجهة نظر هو نهج أفضل ولكن منذ HQL عادة بإرجاع قائمة أو مجموعة ... يمكنك القيام list_1.addAll (list_2). تماما تمتص مقارنة مع اتحاد ولكن يجب أن تعمل.

وربما كان لي مشكلة أكثر على التوالي إلى الأمام لحلها. بلدي 'على سبيل المثال' وكان في نقابة الصحفيين مع السبات كمزود نقابة الصحفيين.

وأنا تقسيم يختار ثلاثة (اثنان في الحالة الثانية) الى عدة وحدد الجمع بين مجموعات عاد نفسي، لتحل محل فعال نقابة جميع ".

ولقد كنت أيضا من خلال هذا الألم - إذا كان الاستعلام يتم إنشاء (مثل معايير السبات) حيوي ثم لم أجد وسيلة عملية للقيام بذلك.

وكان الخبر السار بالنسبة لي أنني التحقيق اتحاد من أجل حل مشكلة الأداء فقط عند استخدام 'أو' في قاعدة بيانات أوراكل.

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



كما باتريك وقال: إلحاق قائمةs من كل حدد ستكون فكرة جيدة ولكن تذكر أنه يتصرف مثل الاتحاد جميع.لتجنب هذه الآثار الجانبية ، والسيطرة فقط إذا كان الكائن هو بالفعل وأضاف في التحصيل النهائي أم لا.إذا لم يكن هناك, ثم إضافته.
شيء آخر يجب أن تهتم به هو أنه إذا كان لديك أي الانضمام في كل حدد, النتيجة ستكون قائمة كائن مجموعة(List<Objetc[]>) لذلك عليك أن تكرار أكثر من ذلك أن تبقي فقط على الكائن الذي تحتاجه.

نأمل أن يعمل.

وهنا هو حالة خاصة، ولكن قد تلهمك لخلق عملك الخاص حولها. والهدف هنا هو لحساب عدد السجلات من جدولين مختلفة حيث تلتقي سجلات معايير معينة. وأعتقد أن هذه التقنية تعمل من أجل أي حالة حيث كنت في حاجة لتجميع البيانات من جداول متعددة عبر / المصادر.

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

QueryParms parms=new QueryParms();
parms.put("PROCDATE",PROCDATE);

Long pixelAll = ((SourceCount)Fetch.row("PIXEL_ALL",parms,logger)).getCOUNT();

وكما ترون هنا، يبدأ الاستعلام اسمه أن ننظر إلى الكثير أويفول مثل بيان الاتحاد:

@Entity
@NamedQueries({
        @NamedQuery(
            name  ="PIXEL_ALL",
            query = "" +
                    "  SELECT new SourceCount(" +
                    "     (select count(a) from PIXEL_LOG_CURR1 a " +
                    "       where to_char(a.TIMESTAMP, 'YYYYMMDD') = :PROCDATE " +
                    "     )," +
                    "     (select count(b) from PIXEL_LOG_CURR2 b" +
                    "       where to_char(b.TIMESTAMP, 'YYYYMMDD') = :PROCDATE " +
                    "     )" +
                    ") from Dual1" +
                    ""
    )
})

public class SourceCount {
    @Id
    private Long   COUNT;

    public SourceCount(Long COUNT1, Long COUNT2) {
        this.COUNT = COUNT1+COUNT2;
    }

    public Long getCOUNT() {
        return COUNT;
    }

    public void setCOUNT(Long COUNT) {
        this.COUNT = COUNT;
    }
}

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

@Entity
@Table(name="DUAL1")
public class Dual1 {
    @Id
    Long ID;
}

لا تنس أن إدراج سجل دمية الخاص بك:

SQL> insert into dual1 values (1);
مرخصة بموجب: CC-BY-SA مع الإسناد
لا تنتمي إلى StackOverflow
scroll top