集合表的 hibernate 条件查询?

标签 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)


     @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 的 Action 寻找一个包装类,并且能够建立 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);

但这使我返回了所有具有 EMAIL 或 POSTAL 的规则,但我想要的是 所有具有 EMAIL 和 POSTAL 的规则 请帮我修改查询。

最佳答案

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

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

对此,我也颇为不满。但是,如您所见,他们已尝试修复它,但一直无法修复,并已将其交给社区来处理。您有几个选择:

  • 使用 HQL 运行查询。
  • 将您的集合关联重写为具有单个 Enum 字段的实际实体类。

  • 你可以这样做:
     @Entity
     public class ActionWrapper {
    
          public Action action;
     }
    

    然后,更新您的关联并相应地查询,以便 Rule有一个 Set<ActionWrapper> .还有其他解决方法,但您基本上不能使用 Criteria@ElementCollection一起。

    更新

    为了进一步限制查询,以确保您获得满足 BOTH 操作的规则,您需要运行子查询并对匹配值进行连接 - 'and'。这样的事情应该工作:
     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 可能会更好。但是,我在其他项目中做过类似的事情,并没有遇到任何问题。

    关于集合表的 hibernate 条件查询?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/7687409/

    相关文章:

    java - 如何在我的测试代码中直接使用 HibernateTemplate

    java - 如何使用注释处理 Hibernate 和 Spring 中的连接查询?

    java - 如何在列注释中设置默认值

    java - 具有一对多关系的 Hibernate Criteria 搜索请求

    java - 在 Spring 项目中实现 JSR-303 注释

    java - Hibernate Criteria - 从两个没有任何关联的表中获取结果

    java - 回滚所有以前的 hibernate 事务

    java - Hibernate Criteria 中的行乘法

    hibernate - Hibernate Criteria API 是否已弃用?如果是,我们应该使用什么 API?

    grails - 依靠 hasMany 关系在 grails 中创建标准