Search code examples
javasqlmysqlhibernatehql

Get random object from SQL database via Hibernate


I have following MySql dependent code ( ORDER BY RAND() ) . I would like to know if there is hibernate HQL alternative for it (admin is boolean tag indicating that the user as an admin). This is working code:

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();
}

Solution

  • Since the Criterion used in the accepted answer is deprecated, I figured out how to do it with the CriteriaBuilder & CriteriaQuery and just wanted to share it here. I used the pattern described here to extend my repository by the custom method:

    @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);
        }
    }
    
    }