【问题标题】:How to convert SQL Query using CriteriaQuery如何使用 CriteriaQuery 转换 SQL 查询
【发布时间】:2019-10-07 13:43:08
【问题描述】:

我想将我的 sql 查询从 SQL 转换为 CriteriaQuery,我有这个 sql 查询:

1)

SELECT * FROM table AS t WHERE id = (SELECT MAX(id) FROM table AS t WHERE t.element_id = 354 AND (name <> 'foo' OR (name = 'bar' AND event = 'foo')));

2)

SELECT tr1.*
FROM table AS tr1
INNER JOIN (SELECT MAX(id) AS id FROM table AS tr WHERE tr.element_id = 354 AND (name <> 'foo' OR (name = 'bar' AND event = 'foo'))) AS tr2
ON tr1.id = tr2.id;

最好的方法是什么?

public Predicate createsubqueryDateGreaterThanTest(CriteriaBuilder cb, Root<? extends Entity> root, Date inputDate){         
        // create the outer query
        CriteriaQuery<Date> cq = cb.createQuery(Date.class);

        Root<Table> rootQuery = cq.from(Table.class);
        Subquery<Table> sub = cq.subquery(Table.class);
        Root<Table> subRoot = sub.from(Table.class);
        //sub.select(subRoot);
        cq.multiselect(rootQuery);
        sub.select(subRoot)
        //cq.multiselect(rootQuery.select(cb.max(Table_.elementId)));
        //sub.select(cb.greatest(cb.get(Entity_.element).get("id")));
        //cq.multiselect(subRoot.select(cb.greatest(Table_.elementId)))
            .where(
                    cb.greaterThanOrEqualTo(subRoot.get(Table_.date), inputDate),
                    cb.equal(root.get(Entity_.element).get("id"), subRoot.get(Table_.elementId)),
                    cb.notEqual(subRoot.get(Table_.name), "foo"),
                    cb.or(
                         cb.equal(subRoot.get(Table_.name), "bar"),
                         cb.and(cb.equal(subRoot.get(Table_.event), 'foo'))
                        )
                );

        return cb.exists(sub);
    }

查询运行但结果不正确。

【问题讨论】:

  • 请提供一些示例代码,说明您使用标准 api 已经取得的成果并描述您的问题。
  • 你为什么要这样做?
  • @SimonMartinelli 我需要使用 CriteriaQuery 来实现搜索过滤器。
  • 请同时提供您正在使用的实体(表格、日期、实体)
  • 如果你使用hibernate作为实现,你可以配置'show_sql'参数来查看你的实现产生的sql查询。

标签: java sql jpa criteria-api jpa-2.1


【解决方案1】:

据我所知,这应该是您的第一个查询的表示。

编辑:现在测试
我现在无法测试它,因为我的数据库没有响应,所以如果它不起作用,我稍后会编辑答案。

对非常量参数使用 ParameterExpression 以确保服务器可以重用查询。否则它需要分析和重新规划它收到的每个新查询。

但在这种情况下,ParamterExpression 似乎无法正常工作,可能是 Hibernate 问题(我使用 5.4.2.Final 进行测试)。

附言: 您应该避免对表标识符使用“sql”关键字,因此不要将表命名为“表”,而是使用其他名称。

SELECT * FROM table AS t WHERE id = (SELECT MAX(id) FROM table AS t WHERE t.element_id = 354 AND (name <> 'foo' OR (name = 'bar' AND event = 'foo')));
        CriteriaQuery<Table> criteriaQuery = cb.createQuery(Table.class);
        Root<Table> root = criteriaQuery.from(Table.class);

        Subquery<Integer> sub = criteriaQuery.subquery(Integer.class);
        Root<Table> subRoot = sub.from(Table.class);

        criteriaQuery.where(
                cb.equal(subRoot.get(Table_.element_id), 354),
                cb.or(cb.notEqual(subRoot.get(Table_.name), "foo"),
                      cb.and(cb.equal(subRoot.get(Table_.name), "bar"), 
                             cb.equal(subRoot.get(Table_.event), "foo"))));

        sub.select(cb.max(subRoot.get(Table_.id)));

        criteriaQuery.where(cb.equal(root.get(Table_.id), sub));
        criteriaQuery.select(root);

        List<Table> result =
        entityManager.createQuery(criteriaQuery)
        .getResultList();

【讨论】:

  • 我目前正在测试。第二个查询是第一个查询的变体。
猜你喜欢
  • 2020-12-27
  • 2014-10-05
  • 2021-09-15
  • 1970-01-01
  • 2020-07-19
  • 2021-10-11
  • 2017-10-29
  • 2015-04-21
  • 2019-04-24
相关资源
最近更新 更多