【问题标题】:Get random object from SQL database via Hibernate通过 Hibernate 从 SQL 数据库中获取随机对象
【发布时间】:2011-05-13 02:06:11
【问题描述】:

我有以下 MySql 依赖代码 (ORDER BY RAND())。我想知道它是否有休眠 HQL 替代方案(管理员是布尔标记,表示用户是管理员)。这是工作代码:

public long getRandomAdmin() {
    Session session = getSession();
    Query selectQuery = session.createSQLQuery("SELECT user_id FROM users WHERE admin = '1' ORDER BY RAND()");
    selectQuery.setMaxResults(1);

    List<BigInteger> list = null;
    try {
        list = selectQuery.list();
    } catch (HibernateException e) {
        log.error(e);
        throw SessionFactoryUtils.convertHibernateAccessException(e);
    }

    if (list.size() != 1) {
        log.debug("getRandomAdmin didn't find any user");
        return 0;
    }
    log.debug("found: " + list.get(0));

    return list.get(0).longValue();
}

【问题讨论】:

标签: java sql mysql hibernate hql


【解决方案1】:

查看此链接: http://www.shredzone.de/cilla/page/53/how-to-fetch-a-random-entry-with-hibernate.html

Criterion restriction = yourRestrictions;
Object result = null;  // will later contain a random entity
Criteria crit = session.createCriteria(Picture.class);
crit.add(restriction);
crit.setProjection(Projections.rowCount());
int count = ((Number) crit.uniqueResult()).intValue();
if (0 != count) {
  int index = new Random().nextInt(count);
  crit = session.createCriteria(Picture.class);
  crit.add(restriction);
  result = crit.setFirstResult(index).setMaxResults(1).uniqueResult();
}

这就是你想要的。保持 Hibernate 作为抽象层,同时仍然能够查询随机对象。不过,性能会受到一点影响。

虽然我一直在使用 Hibernate,但我不知道有什么更优雅且易于使用的方式。恕我直言,您应该将该方法包装在外观后面。

【讨论】:

  • 很难相信 hibernate 不会隐藏这些跨数据库的实现..无论如何这种方式有效[甚至可能比通过 rand() webtrenches.com/post.cfm/avoid-rand-in-mysql 直接订购更快] 虽然它只会返回你一个随机行,所以如果你想要 X 个随机条目,你必须做 X 个查询,FWIW。另一种选择是创建您自己的自定义休眠方言,将 Oracle 的“rand”函数注册为“dbms_random.value”
  • 如果您缺少介于 0 和 maxId 之间的 id,这可能不会返回任何记录。
【解决方案2】:

由于已接受的答案中使用的标准已被弃用,我想出了如何使用 CriteriaBuilder 和 CriteriaQuery 来做到这一点,只是想在这里分享。我使用here 描述的模式通过自定义方法扩展我的存储库:

@Repository
public class UserRepositoryCustomImpl implements UserRepositoryCustom {
@Autowired
EntityManager em;

public User findRandomUserInCountry(String countryCode) throws NotFoundException {
    CriteriaBuilder qb = em.getCriteriaBuilder();
    CriteriaQuery<Long> cqCount = qb.createQuery(Long.class);

    Root<User> userCountRoot = cqCount.from(User.class);

    cqCount.select(qb.count(userCountRoot)).where(qb.equal(userCountRoot.get("countryCode"), countryCode));

    int count = em.createQuery(cqCount).getSingleResult().intValue();

    System.out.println("Count of users: " + count);

    if (0 != count) {
        int index = new Random().nextInt(count);
        CriteriaQuery<User> cqUser = qb.createQuery(User.class);
        Root<User> userRoot = cqUser.from(User.class);
        cqUser.select(userRoot).where(qb.equal(userRoot.get("countryCode"), countryCode));

        User randomUser = em.createQuery(cqUser).setFirstResult(index).setMaxResults(1)
                .getSingleResult();

        System.out.println("Random user: " + randomUser.getName());

        return randomUser;
    } else {
        throw new NotFoundException("No users available in repository for country: " + countryCode);
    }
}

}

【讨论】:

    猜你喜欢
    • 2020-06-10
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多