【问题标题】:Hibernate Criteria API: get n random rowsHibernate Criteria API:获取 n 个随机行
【发布时间】:2011-02-18 03:15:42
【问题描述】:

我不知道如何从条件实例中获取 n 个随机行:

Criteria criteria = session.createCriteria(Table.class);
criteria.add(Restrictions.eq('fieldVariable', anyValue));
...

然后呢?我找不到任何带有 Criteria API 的文档

这是否意味着我应该改用 HQL?

谢谢!

编辑:我通过以下方式获得行数:

int max = criteria.setProjecxtion(Projections.rowCount()).uniqueResult();

如何获取索引在 0 到最大值之间的 n 个随机行? 再次感谢!

【问题讨论】:

    标签: java sql hibernate mysql random


    【解决方案1】:

    实际上可以通过 Criteria 和一些调整来实现。方法如下:

    Criteria criteria = session.createCriteria(Table.class);
    criteria.add(Restrictions.eq("fieldVariable", anyValue));
    criteria.add(Restrictions.sqlRestriction("1=1 order by rand()"));
    criteria.setMaxResults(5);
    return criteria.list();
    

    任何 Restrictions.sqlRestriction 都会添加关键字'and';所以要取消它的效果, 我们将添加一个虚拟条件并注入我们的 rand() 函数。

    【讨论】:

    • 这很方便,对我有帮助!
    • sql限制中1=1的目的是什么。我得到了正确的输出,没有这个我得到一个错误
    • 使用“order by rand()”时存在性能问题,请看:stackoverflow.com/questions/4329396/…
    【解决方案2】:

    首先,请注意在 SQL 中没有标准的方法来执行此操作,每个数据库引擎都使用自己的专有语法1。使用 MySQL,获取 5 个随机行的 SQL 语句将是:

    SELECT column FROM table
    ORDER BY RAND()
    LIMIT 5
    

    您可以在 HQL 中编写此查询,因为 HQL 中的 order by 子句被传递到数据库,因此您可以使用任何函数。

    String query = "SELECT e.attribute FROM MyEntity e ORDER BY RAND()";
    Query q = em.createQuery(query);
    q.setMaxResults(5);
    

    但是,与 HQL 不同,Criteria API 当前不支持 ORDER BY Native SQL(请参阅 HHH-2381),在当前状态下,您必须将 Order 类子类化为实现这个功能。这是可行的,请参阅 Jira 问题,但不是开箱即用的。

    所以,如果你真的需要这个查询,我的建议是使用 HQL。请记住,它不是便携式的。

    1 其他读者可能想查看帖子SQL to Select a random row from a database table,了解如何使用 MySQL、PostgreSQL、Microsoft SQL Server、IBM DB2 和 Oracle 实现此功能。

    【讨论】:

    • Hibernate 告诉我没有“RAND”之类的函数,使用 pg@java7,嗯……什么滴滴错了? -> 如果是 pg,它的 random(),很抱歉打扰
    【解决方案3】:

    Criteria API 不为此提供便利。然而,在 MySQL 中,您可以使用 ORDER BY RAND() LIMIT n ,其中 n 表示您要获取的随机行数。

    SELECT col1, col2, col3 FROM tbl ORDER BY RAND() LIMIT :n
    

    您确实需要将其作为 HQL 执行。

    【讨论】:

      【解决方案4】:

      抱歉,您无法有效地获取随机行。 Hibernate 只能做 SQL 所做的事情,而随机行获取根本不是我所知道的任何标准 SQL 实现的一部分——实际上,据我所知,它不是我所知道的任何 SQL 的一部分(任何人请启发我)。

      由于 Hibernate 是一个 O/R 映射器,而不是一个神奇的机器,它只能做底层数据库支持的事情。

      如果你有一个已知的由升序数字组成的字段并且知道开始和结束,你可以在计算机上生成一个随机数并询问该行。

      【讨论】:

      • 这些都是很好的考虑因素,尽管效率并不是他最关心的问题。
      • Mysql 确实按 rand() 排序
      【解决方案5】:

      如果您要动态生成标准,@PSV Bhat 的答案很困难。这是一个扩展休眠订单类的解决方案:

      import org.hibernate.Criteria;
      import org.hibernate.criterion.Order;
      
      private void addOrderByToCriteria(Criteria criteria) {
          criteria.addOrder(Order.asc("foobar"));
          criteria.addOrder(ORDER_RANDOM);
      }
      
      private static final OrderRandom ORDER_RANDOM = new OrderRandom();
      
      private static class OrderRandom extends Order {
          public OrderRandom() {
              super("", false);
          }
          @Override
          public String toSqlString(Criteria criteria, CriteriaQuery criteriaQuery) {
              return "RANDOM()"; // or RAND() or whatever this is in your dialect
          }
      }
      

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2011-03-18
        • 2014-10-06
        • 2011-11-08
        • 2013-11-12
        • 2013-06-21
        相关资源
        最近更新 更多