Критерии гибернации, помещающие содержит / не содержит ограничение на набор элементов - PullRequest
1 голос
/ 31 января 2011

Привет! Я пытаюсь перевести мою старую инфраструктуру запросов на основе SQL на Hibernate Criteria, в настоящее время я использую Hibernate версии 3.2.и mysql v 5.0.54

Мой вопрос заключается в том, что я хочу написать критерий, который возвращает все Бины, которые не имеют значение в отдельном наборе элементов.

Сводка файла конфигурации hibernate для 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" в их agentOptions

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()
         ));
   ...

, который работал, но кажется немного уродливым.

Кто-нибудь знает, есть ли способ с помощью API-интерфейса std Criteria wi?без необходимости прибегать к sql.

Любая помощь или предложения будут приветствоваться.Даже если они требуют обновления до более поздней версии Hibernate.

Cheers Simon

1 Ответ

0 голосов
/ 12 августа 2011

Структурируйте свой подзапрос как 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)));
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...