繁体   English   中英

jpa条件查询,匹配作为参数传递的任何列表

[英]jpa criteria query, match any of list passed as parameter

我试图编写一种DAO方法,从中选择任意数量的具有匹配标签的Widget。 因此,在像这样的实体中:

@Entity
public class Widget {
    @Id
    private id;

    @OneToMany (cascade = CascadeType.ALL)
    private List<Tag> tagList;
}


@Entity
public class Tag {
    @Id
    private int id;

    String tagValue;
}

在我的DAO中,我正在尝试编写一个将包含字符串列表的方法

List<String> myList = new ArrayList<String>();
myList.add("tom");
myList.add("dick");
myList.add("harry");

到DAO

public List<Widget> getWidgetsMatchingTags(EntityManager entityManager, List<String> tagValues) {
    CriteriaBuilder cb = entityManager.getCriteriaBuilder();
    CriteriaQuery<Widget> query = cb.createQuery(Widget.class);
    Root<Widget> widgetRoot = query.from(Widget.class);
    Join<Widget, Tag> tagJoin = widgetRoot.join(Widget_.tagList);

    // this works
    query.select(widgetRoot).where(cb.and(
           cb.equal(tagJoin.get(Tag_.value), "tom")));

   // but if I try to add another predicate, it does not work, 
   // it returns a list size of 0

   query.select(widgetRoot).where(cb.and(
           cb.equal(tagJoin.get(Tag_.value), "tom")),
           cb.equal(tagJoin.get(Tag_.value), "harry"));

}

希望能够匹配所有或任何给定标签,并认为这将是cb.and()或cb.or()的问题

我谷歌了一圈,发现在几个链接,像这样的集合 ,也是这样 ,我不认为是完全相关的。我也去了直通的PDF文档JPA的在线用户指南 ,并没有看到这涉及明确。 如果我错过了什么请告诉我

还要注意,我需要匹配一个标签值 ,因为字符串是标签obj的一个字段。

谢谢你的帮助!!

谢谢你的帮助

假设Tag上有一个Widget属性,如下所示:

@ManyToOne
private Widget widget;

如果您想匹配任何标签,甚至不需要动态查询。 使用FluentJPA可以实现如下:

List<Object> tags; // passed as a parameter

FluentQuery query = FluentJPA.SQL((Widget w,
                                   Tag tag) -> {
    SELECT(DISTINCT(w));
    FROM(w).JOIN(tag).ON(tag.getWidget() == w);
    WHERE(tags.contains(tag.getTagValue()));
});

query.createQuery(getEntityManager(), Widget.class).getResultList();

如果要匹配所有标签,则需要动态查询:

public List<Widget> filterWidgets(List<String> tags) {
    Function1<Tag, Boolean> dynamicFilter = buildAnd(tags);

    FluentQuery query = FluentJPA.SQL((Widget w,
                                       Tag tag) -> {

        SELECT(DISTINCT(w));
        FROM(w).JOIN(tag).ON(tag.getWidget() == w);
        WHERE(dynamicFilter.apply(tag));
    });
    return query.createQuery(getEntityManager(), Widget.class).getResultList();
}

private Function1<Tag, Boolean> buildAnd(List<String> tags) {
    Function1<Tag, Boolean> criteria = Function1.TRUE();

    for (String tag : tags)
        criteria = criteria.and(t -> t.getTagValue() == parameter(tag));

    return criteria;
}

具有3个标签,这是结果查询:

SELECT DISTINCT t0.*  
FROM Widget t0  INNER JOIN Tag t1  ON (t1.widget_id = t0.id) 
WHERE (((t1.tag_value = ?1) AND (t1.tag_value = ?2)) AND (t1.tag_value = ?3))

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM