2011-01-31 60 views
1

您好我正在嘗試將我的舊的基於SQL的查詢框架遷移到基於Hibernate Criteria,目前我正在使用休眠版本3.2。和mysql v 5.0.54休眠條件把一個包含/不包含一組元素的限制

我的問題是我想寫一個條件返回所有的豆有一個包含的元素集中的值。

Bean的休眠配置文件的摘要:

<hibernate-mapping package="com.mydomain.beans"> 

     <typedef class="com.mydomain.dao.util.HibernateAgentOptionType" name="agent-option"/> 

     <class name="Agent" table="agent"> 
      ... 
      <set name="agentOptions" table="agent_options" fetch="join" lazy="true"> 
       <key column="agt_id"/> 
       <element column="identifier" type="agent-option"/> 
      </set> 
     </class> 
    </hibernate-mapping> 

類文件是一樣的東西:

public class Agent { 
    ... 
    public Set<Option> getAgentOptions() { 
     return agentOptions; 
    } 
    public void setAgentOptions(Set<Option> _agentOptions) { 
     this.agentOptions = _agentOptions; 
    } 

    public enum Option { 
     WEB_SITE_SYNDICATE ("web-site-syndicate"), 
     RECEIVE_PREMIUM_ENQUIRIES ("receive-premium-enquiries"), 
     DO_NOT_SYNDICATE_ADS_TO_THIRD_PARTIES ("do-not-syndicate-ads-to-third-parties") 
    } 
} 

我想找回誰不具備的所有代理其代理程序中的選項「DO_NOT_SYNDICATE_ADS_TO_THIRD_PARTIES」選項

我在此之前使用的SQL狡猾的是這樣的:

SELECT agt.id 
FROM agent agt 
WHERE agt.id NOT IN (
    SELECT sub_agt.id FROM agent sub_agt 
    JOIN agent_options AS agt_options ON agt_options.agt_id = sub_agt.id 
    WHERE agt_options.identifier = 'do_not_syndicate_ads_to_third_parties' 
) 

我已經試過這樣:

... 
    Criteria crit = getHibernateSession().createCriteria(Agent.class); 
    crit.addRestriction(Restriction.not(Restriction.in("agentOptions", noSyndicatedAds))); 
    ... 

哪個吐出不良的SQL

我也試着這樣使用別名:

... 
    crit.createAlias("agentOptions", "agentOption"); 
    crit.add(Restrictions.not(Restrictions.in("agentOption", options))); 
    ... 

這引發了一個例外:

org.hibernate.MappingException:採集是不是關聯:Agent.agentOptions

最後我決定嘗試蠻力SQL標準:

... 
    crit.add(Restrictions.sqlRestriction(" {alias}.id not in " + 
       "(select agt_sub.id " + 
       "from agent agt_sub " + 
       "join agent_options as agent_options_sub on agent_options_sub.agt_id = agt_sub.id " + 
       "where agent_options_sub.identifier in (?)) ", 
       Agent.Option.DO_NOT_SYNDICATE_ADS_TO_THIRD_PARTIES.getIdentifier(), 
       new org.hibernate.type.StringType() 
     )); 
    ... 

哪些工作,但似乎有點難看。

有誰知道是否有方法使用標準的Criteria API,而不必訴諸於SQL。

任何幫助或建議將非常受歡迎。即使他們需要升級到更新版本的Hibernate。

乾杯 西蒙

+0

我也想知道。我有一個具有「描述」字段的子集的父實體。我試圖編寫一個DAO函數,它可以將所有父母的孩子的描述與某些搜索文本相匹配(使用like/ilike)。我可以讓它「工作」,但它爲子表添加了第二個連接,映射添加的內容。我想我真的只是想爲已經發生的連接添加限制。 – spaaarky21 2011-06-27 04:23:00

回答

0

結構的子查詢爲DetachedCriteria,然後用你的嵌套Restrictions實現NOT IN。在你的情況下:

DetachedCriteria subquery = DetachedCriteria.forClass(Agent.class); 
subquery.createAlias("agentOptions", "agentOption"); 
subbquery.add(Restrictions.eq("identifier", Agent.Option.DO_NOT_SYNDICATE_ADS_TO_THIRD_PARTIES.getIdentifier()); 
subquery.setProjection(Projections.property("agt_id")); // only return one field 
crit.add(Restrictions.not(Restrictions.in("agt_id", subquery)));