【发布时间】:2019-08-11 17:45:50
【问题描述】:
我正在尝试编写一个 DAO 方法,我可以在其中选择任意数量的具有匹配标签的小部件。所以在像这样的实体中:
@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() 的问题
我在谷歌上搜索并找到了一些链接,例如 collections 和 this 上的这个链接,我认为这并不完全相关......我还浏览了 pdf jpa 文档,online user guide 并做了没有明确地看到这一点。如果我遗漏了什么,请告诉我
还要注意我需要匹配一个标签值,因为字符串是标签obj的一个字段。
感谢您的帮助!!
感谢您的帮助
【问题讨论】:
-
匹配所有或任何给定标签:你是什么意思?是全部还是全部?
-
希望能够做到,例如传入一个 arg(如布尔值),并取决于值调用
cb.any()或cb.all() -
这不仅仅是将
or变成and的问题。如果你想匹配任何标签,那么你只需要or(或使用tagJoin.get(Tag_.value).in(acceptedTagValues))。你对and所做的事情,OTOH,不能工作,因为它只接受一行,如果它的标签值同时等于“tom”和“harry”,这是不可能的。您需要一个子查询来计算可接受值集中小部件的标记值的数量,并测试该计数是否等于集合的大小。 -
看起来是ManyToMany关系,你不应该有一个额外的表来存储id对吗?
-
我最终解决了这个问题,方法是创建一个子查询,遍历我想在数据库中找到的标签列表,并为给定的搜索文本创建一个子查询的 Predicate 实例。然后我将谓词数组添加到 query.where() 并解决了它。
标签: java hibernate criteria-api