8

私は次のエンティティを持っています

@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の両方を持つすべてのルールですクエリの変更を手伝ってください。

4

3 に答える 3

6

申し訳ありませんが、具体的には、Hibernate ではサポートされていません。この FAQ を参照してください:

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

私もこれにはかなり不満でした。ご覧のとおり、彼らはそれを修正しようとしましたが、修正できず、対処するためにコミュニティに投稿しました. いくつかのオプションがあります:

  1. HQL を使用してクエリを実行します。
  2. コレクションの関連付けを、単一の Enum フィールドを持つ実際のエンティティ クラスとして書き直します。

次のようなことができます。

 @Entity
 public class ActionWrapper {

      public Action action;
 }

次に、関連付けを更新し、それに応じてクエリを実行しRuleて、Set<ActionWrapper>. 他にも回避策はありますが、基本的にCriteriaand を@ElementCollection一緒に使用することはできません。

アップデート

クエリをさらに制限し、両方のアクションを満たすルールを確実に取得するには、サブクエリを実行し、一致した値の結合 (「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 の方が優れている可能性があります。ただし、他のプロジェクトでも同様のことを行っており、問題は発生していません。

于 2011-10-10T06:34:11.843 に答える
3

列挙型をラップせず、ResultTransformersを使用しない別の解決策は次のとおりです。

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

それがHibernate4.1.6.Finalで私のために働いたものです。ここで見つけました。

于 2013-03-06T17:22:49.967 に答える
1

条件クエリは問題ないようです。テーブルがあるとします:

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;
   ...
}

このようにして、条件クエリが機能するはずです。

于 2011-10-07T23:33:16.880 に答える