2011-10-07 17 views
8

मैं इकाईहाइबरनेट मानदंड क्वेरी?

@Entity 
@Table(name = "rule") 
public class Rule implements Serializable { 

    @Id 
    @GeneratedValue(strategy = GenerationType.AUTO) 
    @Column(name = "rule_id") 
    private Long id; 

    @ElementCollection(targetClass = Action.class) 


    @CollectionTable(name = "rule_action", joinColumns = @JoinColumn(name = "rule_id")) 
     @Enumerated(value = EnumType.STRING) 
     @Column(name = "action") 
     private Set<Action> actions; 

//After editing as per jbrookover's suggestion adding a new mapping 
     @OneToMany(cascade = CascadeType.ALL, fetch = FetchType.LAZY) 
     @JoinColumn(name = "rule_id") 
     private Set<RuleAction> ruleActions; 


    } 

के बाद निम्नलिखित है मेरी लड़ाई

public enum Action { 
    PHONE, EMAIL, POSTAL,PHONE_OR_EMAIL, SMS; 
} 

है मैं नियम कार्यों का विशेष सेट होने का एक सूची लाने के लिए मैं कोशिश कर रहा हूँ चाहते हैं तो इस

DetachedCriteria criteria = DetachedCriteria.forClass(Rule.class,"rule"); 
criteria = criteria.createAlias("rule.actions", "action"); 
criteria.add(Restrictions.in("action.name",actionSet)); 
return getHibernateTemplate().findByCriteria(criteria); 

लेकिन org.hibernate.MappingException प्राप्त करना: संग्रह एक एसोसिएशन नहीं था: अपवाद ..

संपादित तो jbrookover मैं RuleAction के रूप में नामित कार्रवाई के लिए एक आवरण वर्ग के लिए जा रहा कोशिश से मार्गदर्शन के बाद और oneToMany संबंध eshtablish करने में सक्षम था, इसके अलावा, मैं क्वेरी संशोधित रूप में

Set<Action> act = new HashSet<Action>(); 
    act.add(Action.EMAIL); 
    act.add(Action.POSTAL); 

    DetachedCriteria criteria = DetachedCriteria.forClass(Rule.class); 
    criteria.add(Restrictions.eq(SUPPORT_LANG, Language.valueOf("EN"))) 
      .createCriteria("ruleActions").add(Restrictions.in("action",act)); 
    return getHibernateTemplate().findByCriteria(criteria); 

इस प्रकार है लेकिन यह मुझे उन सभी नियमों को वापस कर रहा है जिनमें ईमेल या पोस्टस्टल है लेकिन मैं जो चाहता हूं वह है, जिसमें सभी नियम EMAIL और POSTAL दोनों हैं कृपया क्वेरी को संशोधित करने में मेरी सहायता करें।

उत्तर

6

क्षमा करें, आप जो करने की कोशिश कर रहे हैं, विशेष रूप से, हाइबरनेट में समर्थित नहीं है। यह FAQ देखें:

http://community.jboss.org/wiki/HibernateFAQ-AdvancedProblems#Im_getting_orghibernateMappingException_collection_was_not_an_association_when_I_try_to_join_a_collection_of_components_with_Criteria_queries

मैं भी इस के साथ काफी खुश नहीं थे। जैसा कि आप देख सकते हैं, हालांकि, उन्होंने इसे ठीक करने का प्रयास किया है, ऐसा करने में असमर्थ रहे हैं और इसे सौदा करने के लिए इसे समुदाय में डाल दिया है। आपके पास कुछ विकल्प हैं:

  1. क्वेरी चलाने के लिए HQL का उपयोग करें।
  2. एक एकल एनम फ़ील्ड के साथ एक वास्तविक इकाई वर्ग के रूप में अपने संग्रह संघ को फिर से लिखें। तब

    @Entity 
    public class ActionWrapper { 
    
         public Action action; 
    } 
    

    , उसके अनुसार अपनी संगठनों और क्वेरी अपडेट करें कि Rule एक Set<ActionWrapper> है:

आप कुछ इस तरह कर सकते हैं। अन्य कामकाज भी हैं, लेकिन आप अनिवार्य रूप से Criteria और @ElementCollection का उपयोग नहीं कर सकते हैं। 'और' - - मिलान किया मूल्यों की

अद्यतन

आगे क्वेरी को प्रतिबंधित करने के लिए, सुनिश्चित करें कि आप नियम है कि दोनों कार्यों को पूरा मिल में, आप सबक्वेरी चलाने के लिए और एक संयोजन के रूप की ज़रूरत है।इस तरह कुछ काम करना चाहिए:

Criteria subCriteria = criteria.createCriteria("ruleActions"); 
Disjunction and = Restrictions.conjunction(); 
for (Action a : act) 
    and.add(Restrictions.eq("action", a) 
subCriteria.add(and); 

अंत में, आपको डुप्लिकेट परिणाम मिल सकते हैं। यह आम है और इस जोड़कर समाप्त किया जा सकता:

criteria.setResultTransformer(Criteria.DISTINCT_ROOT_ENTITY); 

मैं इस कोड की दक्षता के लिए नहीं बोल सकता - HQL लंबे समय में बेहतर हो सकता है। हालांकि, मैंने अन्य परियोजनाओं में कुछ ऐसा किया है और किसी भी मुद्दे का सामना नहीं किया है।

 @ElementCollection(fetch = FetchType.EAGER) 
     @Enumerated(value = EnumType.STRING) 
     @Column(name = " action") 
     @JoinTable(name = "rule_action", joinColumns = { @JoinColumn(name = "rule_id") }) 
     private Set<Action> actions; 

क्वेरी::

DetachedCriteria criteria = DetachedCriteria.forClass(Rule.class,"rule"); 
criteria = criteria.createAlias("rule.actions", "action"); 
criteria.add(Restrictions.in("action." + CollectionPropertyNames.COLLECTION_ELEMENTS, actionSet)); 
return getHibernateTemplate().findByCriteria(criteria); 

क्या हाइबरनेट 4.1.6.Final साथ मेरे लिए काम किया है कि

+0

हाय jbrookover .. धन्यवाद !! आपके सुझाव के अनुसार मैं रैपर क्लास के माध्यम से आगे बढ़ने की कोशिश कर रहा हूं। और जो कुछ भी मैं कर रहा हूं उसके अनुसार आपका उत्तर संशोधित कर दिया है। इसलिए यह अन्य समस्याओं की सहायता कर सकता है जो एक ही समस्या का सामना कर सकते हैं –

+0

@ अनुपम गुप्ता प्रतिबंधित क्वेरी को शामिल करने के लिए अपडेट किया गया। – jbrookover

+0

धन्यवाद @ jbrookover अब तक मैंने एचक्ल का उपयोग किया..और आपके समाधान का उपयोग करने के लिए काफी कब्जा कर लिया गया है जल्द ही इसे आपके सुझाव के अनुसार बदल देगा और एसओ में भी अपडेट होगा, ताकि यह दूसरों के लिए उपयोगी हो सके –

1

मानदंड क्वेरी ठीक दिखती है। मान लीजिए कि हमें टेबल है:

rule(id, name,...) 
action(id, name,..) 
rule_action(id, rule_id, action_id,...) -- (or rule_id+action_id as a composite pkey) 

मानचित्रण इस प्रकार होना चाहिए:

public class Rule { 
    ... 
    @ManyToMany(mappedBy = "rule") 
    private Set<Action> actions; 
    ... 
} 

public class Action { 
    ... 
    @JoinTable(
     name="rule_action", 
     joinColumns={@JoinColumn(name="action_id")}, 
     inverseJoinColumns={@JoinColumn(name="rule_id")} 
    ) 
    private Set<Rule> rules; 
    ... 
} 

इस तरह आपके मानदंड क्वेरी काम करना चाहिए।

+0

HI क्या आप कृपया मुझे बता सकते हैं कि उपर्युक्त मामले के लिए हाइबरनेट मानदंड क्वेरी कैसे लिखनी है, मैं इस तरह के मानदंडों को जोड़ना चाहता हूं कि मेरी क्वेरी को ए और डी (क्रियाओं के सेट से बाहर {ए, बी, सी, डी, ई}) –

+0

हाय, मुझे खेद है, जाहिर है, मैं सावधानी से प्रश्नों को पढ़ने में बुरा हूं। प्रारंभिक उत्तर पूरी तरह से भ्रामक था, इसलिए मैंने इसे पूरी तरह से फिर से लिखा। जरा देखो तो। – forker

+0

असल में मैं मैपिंग को बदलने के बारे में चिंतित हूं क्योंकि वर्तमान कोड कलेक्शनटेबल का उपयोग कर रहा है। और वर्तमान मैपिंग का व्यापक रूप से उपयोग किया जाता है, इसलिए मैं यह सुनिश्चित करना चाहता हूं कि मैं मौजूदा कोड को तोड़ नहीं रहा हूं .. क्या आपके द्वारा बताए गए मैपिंग को बदलना मौजूदा सिस्टम को प्रभावित करेगा? –

3

अपने enums लपेटकर और ResultTransformers का उपयोग किए बिना एक अन्य समाधान यह है। मैंने इसे here पाया।

+0

धन्यवाद, यह बहुत अच्छा काम करता है मुझे! – George

संबंधित मुद्दे