使用动态列表使用 jpa 2.0 构建条件查询

发布于 2024-12-04 06:57:47 字数 2546 浏览 0 评论 0原文

我在使用 JPA 2.0 创建 criteriaQuery 时有点困惑。

先决条件:
我有一个 Gui,用户可以在其中标记(比方说)气象站的一些复选框,其中包含一些选项,例如温度/风/时间段/等...

现在我想设置一个 criteriaQuery 以仅从 sql 中选择选定的项目数据库并将其作为对象/地图/列表返回以构建一些数据模型(这将用于生成一些 primefaces 图表)。

到目前为止我所拥有的:

// for presentation purposes just this mockup-data
Calendar start = new GregorianCalendar(2011, Calendar.APRIL, 1);
Calendar end = new GregorianCalendar(2011, Calendar.MAY, 1);
List<String> selectedStations = new LinkedList<String>() {{
    add("PS1");
    add("PS2");
    add("PS3");
}};
Map<String, Object selectedOptions = new LinkedHashMap<String, Object>() {{
    put("opt1","val1");
    put("opt2","val2");
    put("opt3","val3");
}};
List<String> sel = new LinkedList<String>() {{
    add("selOpt1");
    add("selOpt2");
    add("selOpt3");
}};

criteriaBuilder、criteriaQuery 和映射类:

// go for the criteriaBuilder
CriteriaBuilder cb = em.getCriteriaBuilder();
CriteriaQuery<Tuple> cq = cb.createTupleQuery();
Root<StationItem> r = cq.from(StationItem.class);

设置谓词:

// ... where (name="PS1" or name="PS2" or name="PS3") ...
Predicate p1 = cb.disjunction();
for (String s : selectedStations) {
    p1 = cb.or(p1, cb.equal(r.get("name").as(String.class), s));
}
Predicate p2 = cb.between(r.get("fetchDate").as(Date.class),
    start.getTime(), end.getTime());
Predicate p3 = cb.conjunction();
for (Map.Entry<String, Object> param : selectedOptions.entrySet())
    p3 = cb.and(p3, cb.equal(r.get(param.getKey()), param.getValue()));

运行查询并获取结果的最后一步:

此时我做不知道用我的选择填充多选标准的最佳方法是什么。我想以某种动态方式将列表 sel 中的所有项目/选择插入到 cq.multiselect() 中...
欢迎任何想法!

// This is working but static :(
cq.multiselect(r.get(sel.get(0)), r.get(sel.get(1)), r.get(sel.get(2)));

// i would prefer to have something like 
for (int i=0;i<sel.size();i++) {
    cq.multiselect().add(r.get(sel.get(i)));
}

连接我的 WHERE 子句和执行查询:

cq.where(cb.and(p1,p2,p3));

List<Tuple> res = em.createQuery(cq).getResultList();
for (Tuple t : res) {
    // do something ...
};
return <something useful>

通过伪 SQL 查询来总结我想要实现的目标:

SELECT {items from List<String> sel}
FROM MyStationDatabase
WHERE (name = selectedStation.get(0) OR ... OR name = selectedStation.get(last))
    AND {items from Map<String,Object> selectedOptions}

I'm a bit confused while creating a criteriaQuery with JPA 2.0.

Prerequisites:
I have a Gui, where the user can mark some checkboxes of (let us say) wheatherstations with some options like temperature/wind/timeperiod/etc...

Now I want to set up a criteriaQuery to pick just the selected items from a sql database and return it as an object/Map/List for building some DataModels (this will be used for generating a few primefaces charts).

What i have so far:

// for presentation purposes just this mockup-data
Calendar start = new GregorianCalendar(2011, Calendar.APRIL, 1);
Calendar end = new GregorianCalendar(2011, Calendar.MAY, 1);
List<String> selectedStations = new LinkedList<String>() {{
    add("PS1");
    add("PS2");
    add("PS3");
}};
Map<String, Object selectedOptions = new LinkedHashMap<String, Object>() {{
    put("opt1","val1");
    put("opt2","val2");
    put("opt3","val3");
}};
List<String> sel = new LinkedList<String>() {{
    add("selOpt1");
    add("selOpt2");
    add("selOpt3");
}};

criteriaBuilder, criteriaQuery and the mapping class:

// go for the criteriaBuilder
CriteriaBuilder cb = em.getCriteriaBuilder();
CriteriaQuery<Tuple> cq = cb.createTupleQuery();
Root<StationItem> r = cq.from(StationItem.class);

Setting up the predicates:

// ... where (name="PS1" or name="PS2" or name="PS3") ...
Predicate p1 = cb.disjunction();
for (String s : selectedStations) {
    p1 = cb.or(p1, cb.equal(r.get("name").as(String.class), s));
}
Predicate p2 = cb.between(r.get("fetchDate").as(Date.class),
    start.getTime(), end.getTime());
Predicate p3 = cb.conjunction();
for (Map.Entry<String, Object> param : selectedOptions.entrySet())
    p3 = cb.and(p3, cb.equal(r.get(param.getKey()), param.getValue()));

And the final step to run the query and fetching the results:

At this point I do not know what is the best approach to fill the multiselect criteria with my selections. I would like to insert all items/selections from the List sel to cq.multiselect() with some kind of a loop in a dynamic way...
Any idea is welcome!

// This is working but static :(
cq.multiselect(r.get(sel.get(0)), r.get(sel.get(1)), r.get(sel.get(2)));

// i would prefer to have something like 
for (int i=0;i<sel.size();i++) {
    cq.multiselect().add(r.get(sel.get(i)));
}

Concatenating my WHERE-clause and executing the query:

cq.where(cb.and(p1,p2,p3));

List<Tuple> res = em.createQuery(cq).getResultList();
for (Tuple t : res) {
    // do something ...
};
return <something useful>

Following a pseudo SQL query to sum up what I want to achieve:

SELECT {items from List<String> sel}
FROM MyStationDatabase
WHERE (name = selectedStation.get(0) OR ... OR name = selectedStation.get(last))
    AND {items from Map<String,Object> selectedOptions}

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(1

静若繁花 2024-12-11 06:57:47

好吧,有时这太微不足道了 -.-

用动态列表填充 cq.multiselect() 的一种方法是创建一个选择列表并将其传递给我的多选查询。

List<Selection<?>> s = new LinkedList<Selection<?>>();

for (String item : sel) {
    s.add(r.get(item));
}

cq.multiselect(s);

很容易,但也许有人也有同样的困难:)
即使没有,也可以将其视为 criteriaQuery 的示例;)

Well, sometimes it's too trivial to be true -.-

One way to fill the cq.multiselect() with my dynamic list is to just create a list of selections and pass this over to my multiselect-query.

List<Selection<?>> s = new LinkedList<Selection<?>>();

for (String item : sel) {
    s.add(r.get(item));
}

cq.multiselect(s);

easy, but maybe someone has the same struggles with this :)
and even if not, see it as an example for a criteriaQuery ;)

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文