集合表的Hibernate条件查询?

集合表的Hibernate条件查询?,hibernate,hibernate-criteria,Hibernate,Hibernate Criteria,我有以下实体 @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)

我有以下实体

@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;


    }
我想获取具有特定操作集的规则列表 我正在尝试这个

 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关系,我还修改了查询,如下所示

    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);
Set act=new HashSet();
添加(Action.EMAIL);
增加(邮政行动);
DetachedCriteria=DetachedCriteria.forClass(Rule.class);
标准.添加(限制.eq(支持语言、语言、价值)
.createCriteria(“ruleActions”)。添加(限制。在(“action”,act));
返回getHibernateTemplate().findByCriteria(条件);

但这将返回所有包含电子邮件或邮政的规则,但我想要的是所有包含电子邮件和邮政的规则请帮助我修改查询。

条件查询看起来很好。假设我们有桌子:

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;
   ...
}
公共类规则{
...
@许多(mappedBy=“规则”)
私人行为;
...
}
公共集体诉讼{
...
@可接合(
name=“规则\行动”,
joinColumns={@JoinColumn(name=“action_id”)},
inverseJoinColumns={@JoinColumn(name=“rule_id”)}
)
私人制定的规则;
...
}

这样,您的条件查询应该可以工作。

很抱歉,Hibernate不支持您尝试执行的操作。请参阅此常见问题解答:

一、 我也很不高兴。但是,正如你所看到的,他们试图解决这个问题,但却无法做到,并让社区来处理这个问题。您有几个选择:

  • 使用HQL运行查询
  • 将集合关联重新编写为具有单个枚举字段的实际实体类 您可以这样做:

     @Entity
     public class ActionWrapper {
    
          public Action action;
     }
    
    然后,更新关联并相应地进行查询,以便
    规则
    具有
    。还有其他解决方法,但基本上不能同时使用
    标准
    @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可能会更好。但是,我在其他项目中也做过类似的工作,没有遇到任何问题。

    另一个没有包装枚举和使用ResultTransformer的解决方案是:

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

    这就是Hibernate4.1.6.Final对我起作用的地方。我找到了。

    您好,您能告诉我如何为上述情况编写hibernate条件查询吗?我想添加条件,以便我的查询应返回所有具有操作a和D的规则(操作集合之外{a、B、C、D、E})。您好,对不起,显然我不擅长仔细阅读问题。最初的答案完全是误导性的,所以我完全重写了它。看一看。实际上,我有点担心更改映射,因为当前代码正在使用CollectionTable。当前的映射被广泛使用,所以我只想确保我没有破坏现有的代码。。像您所说的那样更改映射是否会影响现有系统?此外,很抱歉,我没有提到我的操作属于Enum类型。。我已经用行动实体更新了问题。并且已经开始了50分的悬赏。嗨,杰布罗科弗。谢谢!!根据你的建议,我正在尝试完成包装器类。并根据我正在做的事情修改了你的答案,以便它可以帮助其他可能面临同样问题的人problem@AnupamGupta更新为包含受限查询。感谢@jbrookover截至目前我使用的是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);