2010-01-09 6 views
5

के बिना एक हाइबरनेट मानदंड-क्वेरी में एक समूह जोड़ें, मेरे पास तालिका ए से इकाइयों का चयन करने के लिए एक दूसरी तालिका बी में शामिल एक मानदंड-क्वेरी है, समस्या यह है कि यह क्वेरी तालिका ए से कुछ इकाइयों को वापस लाती है बार। लेकिन मुझे परिणामों को अलग होने की जरूरत है।प्रोजेक्शन

Criteria.DISTINCT_ROOT_ENTITY का उपयोग बेकार है, क्योंकि यह SQL-क्वेरी निष्पादित होने के बाद कई अवसरों को फ़िल्टर करता है। इसलिए, जब मैं अपने परिणामों को 20 हिट तक सीमित करता हूं, तो मैं केवल 4 के साथ समाप्त होता हूं, हालांकि अधिक प्रविष्टियां होती हैं, जो मेरी क्वेरी से मेल खाते हैं।

शुद्ध एसक्यूएल में मैं बस क्वेरी में "ग्रुप बाय आईडी" जोड़ सकता हूं और सबकुछ ठीक है, क्योंकि टेबल बी में शामिल होने के लिए केवल तालिका ए से इकाइयों का चयन करने के लिए उपयोग किया जाता है लेकिन मानदंड-एपीआई I के साथ ऐसा नहीं कर सकता अनुमानों का उपयोग करके "ग्रुप बाय" जोड़ने का एकमात्र तरीका है। लेकिन फिर, मैं स्केलर मूल्यों के साथ समाप्त होता हूं, न कि मेरी कक्षा के वास्तविक उदाहरण के साथ। SQL-प्रतिबंध का उपयोग करना या तो काम नहीं करता है, क्योंकि हाइबरनेट मेरे "ग्रुप बाय" -क्लोज़ के बाद एक फर्जी "1 = 1" जोड़ता है। :(

कोई भी विचार?

+0

परिभाषा के अनुसार 'ग्रुप बाय', डेटा के एकत्रीकरण में शामिल है, यही कारण है कि अनुमान आवश्यक हैं। शायद यदि आपने टेबल के अधिक विवरण जोड़े हैं, और SQL क्वेरी आप हाइबरनेट उत्पन्न करना चाहते हैं, तो हम बेहतर सलाह दे सकते हैं। – skaffman

+0

मेरे पास एक क्लास इवेंट है। इस वर्ग की तिथियों की एक सूची है। (असल में ये तिथियां एक विशेष श्रेणी डेटवापर हैं, जो तिथि को लपेटती है और एक आईडी जोड़ती है, क्योंकि हाइबरनेट इस समय मूल्य-टाइप किए गए संग्रह में शामिल नहीं हो सकता है)। मैं घटनाओं से पूछताछ करना चाहता हूं और एक्स और वाई के बीच एक या अधिक घटनाओं के साथ सभी घटनाओं को ढूंढना चाहता हूं। जब मैं SQL-क्वेरी को पकड़ता हूं, जो मानदंड-एपीआई द्वारा उत्पन्न किया गया था और "ग्रुप बाय आईडी" जोड़ता है, यह वही करता है, जो मैं ढूंढ रहा हूं। लेकिन मुझे ग्रुप बाय जोड़ने में हाइबरनेट को बहस करने का कोई तरीका नहीं मिल रहा है! –

उत्तर

0

यह संभव है वास्तविक एसक्यूएल प्रश्नों जो हाइबरनेट संस्थाओं वापस जाने के लिए उपयोग कर सकते हैं लिखने के लिए। तो अगर आप वास्तव में करने के लिए, आप HQL बाईपास और वास्तव में क्वेरी आप अपने ग्रुप के साथ लिख सकता है की जरूरत है । उस में से

जानकारी के लिए here देखें

उदाहरण के लिए यदि आप अपने hbm.xml फ़ाइल में इस तरह एक प्रश्न कुछ परिभाषित कर सकते हैं:।

<sql-query name="exampleQuery"> 
<query-param name="param" type="int"/> 
<return alias="x" class="foo.bar.X"/> 
<return alias="y" class="foo.bar.Y"/> 
    <![CDATA[ 
     select {x.*}, {y.*} 
     from XEntity x 
     inner join YEntity y on y.xId = x.id 
     where y.value = :param 
    ]]> 
</sql-query> 

नोट करें {x। } और {वाई।} इकाई एक्स और इकाई वाई

+0

आपके उत्तर के लिए धन्यवाद :) लेकिन मैं एचक्यूएल का उपयोग नहीं कर रहा हूं। मैं मानदंड-एपीआई का उपयोग कर रहा हूं और मैं इसके लिए बाध्य हूं, क्योंकि क्वेरी को गतिशील रूप से संकलित किया जाना है! इसलिए, मुझे अनुमानों का उपयोग किए बिना आईडी-प्रॉपर्टी द्वारा परिणामों को समूहित करने के लिए हाइबरनेट को बताने का एक तरीका खोजने की आवश्यकता है, क्योंकि मुझे अपने वर्गों के वास्तविक उदाहरणों को पुनर्विक्रय के रूप में नहीं, स्केलर मानों की आवश्यकता है। –

+0

ऊपर दिखाए गए नामित क्वेरी के बजाए प्रोग्रामेटिक रूप से मूल SQL क्वेरी निर्दिष्ट करना भी संभव है - हालांकि मानदंड API का उपयोग करके नहीं। – alasdairg

1

के सभी गुणों का चयन करने के लिए शॉर्टंड सिंटैक्स क्या आपने इस तरह कुछ उपयोग करने का प्रयास किया है?

 ICriteria criteria = dc.GetExecutableCriteria(RepositoryInstance.Session) 
           .SetProjection(
            Projections.Distinct(Projections.ProjectionList() 
             .Add(Projections.Property("Prop1"),"Prop1") 
             .Add(Projections.Property("Prop2"),"Prop2") 
             .Add(Projections.Property("Prop3"),"Prop3") 
             .Add(Projections.Property("Prop4"),"Prop4"))); 
result = criteria.List(); 

आप कक्षा के प्रतिबिंब के माध्यम से गतिशील रूप से गुण जोड़ सकते हैं।

यह इस तरह एसक्यूएल बनाता है: select distinct prop1,prop2,prop3,prop4 from yourClass

मैं DetachedCriteria dc शामिल नहीं किया था के बाद से है कि अप्रासंगिक है।

1

ग्रुप द्वारा अनुमान के बिना: इसकी संभव नहीं यह समझ बनाने के रूप में, कई जवाब में आप, पाया हो सकता है, लेकिन ज्यादातर लोगों को, प्रक्षेपण का उपयोग करने की आवश्यकता होती है क्योंकि इससे उन्हें हर विशेषता परियोजना के लिए नहीं करना चाहते हैं, लेकिन आवश्यकता यह है कि एक बीन का अनुमान लगाया जाना चाहिए। (और परिणामस्वरूप लौट आया)। उदाहरण के लिए मैंने परिणामस्वरूप आवश्यक वस्तु के रूप में bean की कोशिश की है।

मैं चाल का एक छोटा सा मेरा मानना ​​है कि साथ ही परिणाम हासिल किया है, सबसे पहले मैं प्रक्षेपण के बिना द्वारा समूह लागू करने के लिए कोशिश कर रहा था, लेकिन मैं कोई समाधान मिल गया है, तो मैं प्रोजेक्शन पर भरोसा करने के लिए है।

यहाँ मैं क्या

select p.* FROM parent p INNER JOIN child c ON p.id_parent=c.id_father 
WHERE c.child_name like '%?%' AND p.parent_name like '%?%' 
group by p.id_parent 

जावा कोड मैं p.* चाहता था एक Parent वर्ग जो मेरे इकाई सेम है होना करने के लिए है और मैं इसे अद्वितीय होना चाहता था में प्राप्त करने के लिए करना चाहता था है, एक तरह से एक में परिणाम सूची प्राप्त है सेट करें, लेकिन मुझे कई कारणों से इस तरह से पसंद नहीं है :)

इसलिए मैंने के बजाय Child.class से मानदंड बनाया, और यह चाल मेरे लिए काम करती है।

Criteria c = session.createCriteria(Child.class,"c");// starting from Child 
    c.add(Restrictions.like("childName", "abc", MatchMode.ANYWHERE)); 
    c.createAlias("parent", "p"); //remember parent is an attribute in Child.class 
    c.add(Restrictions.like("p.parentName", "xyz", MatchMode.ANYWHERE)); 
    c.setProjection(Projections.projectionList().add(Projections.groupProperty("parent"))); //projecting parent which is an attribute of Child.class 

    List<Parent> result = c.list(); //get the result 
    for (Parent p: result) { 
     System.out.println(p); 
    } 

यदि आपको अभी भी यह विचार नहीं मिला है कि मेरे मैप किए गए एंटिटी बीन क्लासेस हैं।

package com.mazhar.beans; 

import static javax.persistence.GenerationType.IDENTITY; 

import java.util.List; 

import javax.persistence.CascadeType; 
import javax.persistence.Column; 
import javax.persistence.Entity; 
import javax.persistence.FetchType; 
import javax.persistence.GeneratedValue; 
import javax.persistence.Id; 
import javax.persistence.OneToMany; 
import javax.persistence.Table; 

@Entity 
@Table(name = "parent") 
public class Parent { 
    private Integer idParent; 
    private String parentName; 
    private List<Child> childs; 

    @Id 
    @GeneratedValue(strategy = IDENTITY) 
    @Column(name = "id_parent") 
    public Integer getIdParent() { 
     return idParent; 
    } 
    public void setIdParent(Integer idParent) { 
     this.idParent = idParent; 
    } 

    @Column(name = "parent_name") 
    public String getParentName() { 
     return parentName; 
    } 
    public void setParentName(String parentName) { 
     this.parentName = parentName; 
    } 

    @OneToMany(fetch=FetchType.LAZY, mappedBy="parent", cascade=CascadeType.ALL) 
    public List<Child> getChilds() { 
     return childs; 
    } 
    public void setChilds(List<Child> childs) { 
     this.childs = childs; 
    } 

} 

और मेरे बच्चे वर्ग

package com.mazhar.beans; 

import static javax.persistence.GenerationType.IDENTITY; 

import javax.persistence.CascadeType; 
import javax.persistence.Column; 
import javax.persistence.Entity; 
import javax.persistence.FetchType; 
import javax.persistence.GeneratedValue; 
import javax.persistence.Id; 
import javax.persistence.JoinColumn; 
import javax.persistence.ManyToOne; 
import javax.persistence.Table; 

@Entity 
@Table(name = "child") 
public class Child { 
    private Integer idChild; 
    private String childName; 
    private Parent parent; //this actually we projected in criteria query. 

    @Id 
    @GeneratedValue(strategy = IDENTITY) 
    @Column(name = "id_city", unique = true, nullable = false) 
    public Integer getIdChild() { 
     return idChild; 
    } 

    public void setIdChild(Integer idChild) { 
     this.idChild = idChild; 
    } 

    @Column(name = "city_name", nullable = false) 
    public String getChildName() { 
     return childName; 
    } 

    public void setChildName(String cName) { 
     this.childName = cName; 
    } 

    @ManyToOne(fetch = FetchType.LAZY, cascade = CascadeType.ALL) 
    @JoinColumn(name = "id_father") 
    public Parent getParent() { 
     return parent; 
    } 

    public void setParent(Parent parent) { 
     this.parent = parent; 
    } 
} 
0

जिस तरह से आप चाहते हैं में पेश बिना द्वारा समूहीकरण, की मुख्य समस्या यह है कि Oracle जैसे कुछ डीबीएमएस यह काम नहीं करेगा में, ओरेकल एक वापस आ जाएगी त्रुटि।

यदि आप कोई चयन समूह करते हैं, तो आपको अपने द्वारा चुने गए सभी गैर-समेकन फ़ील्ड द्वारा समूह करना होगा। उदाहरण के लिए MySQL में यह प्रतिबंध नहीं है।

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