hibernate标准对一组元素进行包含/不包含限制
您好,我正在尝试将旧的基于 sql 的查询框架迁移到基于 Hibernate Criteria 的框架,目前我正在使用 Hibernate 版本 3.2。和 mysql v 5.0.54
我的问题是我想编写一个标准,返回所有在包含的元素集中没有具有值的 Bean。
bean 的 hibernate 配置文件摘要如下:
<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")
}
}
我想检索所有在其 agentOptions 中没有选项“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()
));
...
它有效,但看起来有点难看。
有谁知道是否有一种方法可以使用 std Criteria API 而不必求助于 sql。
任何帮助或建议将非常受欢迎。即使他们需要升级到更新版本的 Hibernate。
干杯 西蒙
Hi I'm trying to migrate my old sql based query framework to be Hibernate Criteria based, currently I'm using Hibernate version 3.2. and mysql v 5.0.54
My question is I want to write a criteria that returns all the Beans that do not have a value in a contained set of elements.
A summary of the hibernate config file for the bean is:
<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>
The class file is something like:
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")
}
}
I would like to retrieve all the agents who do not have the Option "DO_NOT_SYNDICATE_ADS_TO_THIRD_PARTIES" in their agentOptions
the sql that I was using for this previously was something like:
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'
)
I've tried this:
...
Criteria crit = getHibernateSession().createCriteria(Agent.class);
crit.addRestriction(Restriction.not(Restriction.in("agentOptions", noSyndicatedAds)));
...
Which spits out bad sql
I've also tried this using aliases:
...
crit.createAlias("agentOptions", "agentOption");
crit.add(Restrictions.not(Restrictions.in("agentOption", options)));
...
Which throws an exception:
org.hibernate.MappingException: collection was not an association: Agent.agentOptions
Finally I decided to try a brute sql Criterion:
...
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()
));
...
Which worked but seems a little bit ugly.
Does anyone know if there is a way using the std Criteria API without having to resort to sql.
Any help or suggestions would be very welcome. Even if they require upgrading to a more recent version of Hibernate.
Cheers
Simon
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(1)
将子查询构造为
DetachedCriteria
,然后使用嵌套的Restrictions
来实现NOT IN
。在你的情况下:Structure your subquery as a
DetachedCriteria
, and then use your nestedRestrictions
to achieve aNOT IN
. In your case: