是否可以通过ElementCollections查询JPA实体,其中ElementCollection包含给定元素集中的所有元素?

时间:2015-04-24 16:25:18

标签: jpa jpql jpa-2.1

如何使用JPQL通过ElementCollections查询JPA实体,其中ElementCollection包含给定元素集中的所有元素?

例如,如果Node实体定义了“属性”的ElementCollection

@ElementCollection(fetch=FetchType.EAGER)
@CollectionTable(name="node_attributes", joinColumns=@JoinColumn(name="node_name"))
@MapKeyColumn(name="name")
@Column(name="value")
Map<String, String> attributes = new HashMap<String, String>();

我想找到具有一组给定属性的所有Node实体。我试过以下希望'会员'支持收藏。

"SELECT n FROM Node n WHERE :attributes MEMBER OF n.attributes"

此查询始终返回空列表。这个用例是否可以使用简单的JPQL查询?

1 个答案:

答案 0 :(得分:2)

从JPA 2.0规范,章节 4.4.4路径表达式

  

标识变量,后跟导航操作符(。)和   状态字段或关联字段是路径表达式。的类型   路径表达式是作为导航结果计算的类型;   也就是说,状态字段或关联字段的类型   表达式导航。

     

由KEY,VALUE或ENTRY限定的标识变量   operator是一个路径表达式。 KEY,VALUE和ENTRY运算符可以   仅适用于对应的识别变量   地图关联地图值元素集

     

使用ENTRY运算符的路径表达式是终端。它不可能是   进一步编写,只能出现在查询的SELECT列表中。

这个理论太多了。至于问题,我会看到三个略有不同的答案,具体取决于您是要按Map.KeyMap.Value还是Map.Entry进行搜索:

String qlKeys = "SELECT DISTINCT n " +
                "FROM Node n JOIN n.attributes a " +
                "WHERE KEY(a) IN :keys";
List<Node> nodes = em.createQuery(qlKeys, Node.class)
                     .setParameter("keys", Arrays.asList("foo", "bar"))
                     .getResultList();
String qlValues = "SELECT DISTINCT n " +
                  "FROM Node n JOIN n.attributes a " +
                  "WHERE VALUE(a) IN :values";
List<Node> nodes = em.createQuery(qlValues, Node.class)
                     .setParameter("values", Arrays.asList("baz", "qux"))
                     .getResultList();

请记住,ENTRY运算符只能出现在SELECT子句中,我们可能必须用KEY和VALUE运算符的结合替换它,即

SELECT DISTINCT n 
FROM Node n JOIN n.attributes a
WHERE KEY(a) IN :keys AND VALUE(a) IN :values

在上面的例子中:

  • 标识变量c
  • 表示
  • 路径表达式c.attributes
  • 表示
  • 关联字段a
  • 表示