我有以下实体
@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的指导下,我尝试为Action命名为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);
但是,这将返回所有具有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
我对此也很不满意。但是,正如您所看到的,他们已经尝试修复它,但一直未能做到,并已将其发布给社区以对其进行处理。您有几种选择:
您可以执行以下操作:
@Entity public class ActionWrapper { public Action action; }
然后,更新您的关联并进行相应的查询,以使其Rule具有Set<ActionWrapper>。还有其他解决方法,但是您基本上不能同时使用Criteria和@ElementCollection。
Rule
Set<ActionWrapper>
Criteria
@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可能更好。但是,我在其他项目中也做过类似的事情,没有遇到任何问题。