项目中要求随机取得user表的一条记录。用到hibernate,底层数据库是mysql.
1.首先会想到一种方式:取出数据库中所有的记录,你懂的。一个List,然后list.get(new Random().nextInt(list.size));但显然查询了所有的记录,如果表特别大,效率可想而知。
2. 可行的方式,应该是得到一个随机的主键,然后load.原生sql实现的方式是:select * from user order by rand() limit 1;插一句,很奇怪,有人说这种方式会慢慢的;还有朋友说这种方式rand()有可能返回null.我没有深入了解数据库的实现,但是我想:数据库对于每 插入的一条记录,生成一个index是多么正常。就像这样。
那么数据库感知到index有存在是多么正常,既然index本身就像一个数组索引,那么得到一条随机记录是多么正常,数据库对于暴露得到一条随机记录又是多么正常。那么对于mysql来说,提供rand()是多么正常。那rand()为什么会返回null.这个API理应由数据库来做,那么效率低又何以见得。。。
3.hql居然不支持rand()。createCriteria不太会啊。
4.万般无奈,我在dao.impl层写了个方法,调用createSQLQuery。我愚笨,就像这样
(User)getHibernateTemplate().execute( new HibernateCallback() {
居然会报cast Exception,到底返回什么呢,我不知道。又试着强制转换为ResultSet,也是一样的错误。
5.幸好的generator id方式比较有规律,是auto_increment的。解决方式是这样的。如下
public User loadRandomUser() throws Exception { int count = countAll("User"); User user = null; while (user == null) { int rand = new Random().nextInt(count); final String hql = "from User where privilege=1 and uid = " + rand; user = (User) getHibernateTemplate().execute( new HibernateCallback() { public Object doInHibernate(Session session) throws HibernateException { Query query = session.createQuery(hql); query.setMaxResults(1); return query.uniqueResult(); } }); } return user; }
首先取得记录的总数。随机得一个uid,然后load。随机取记录,由java来做的,效率肯定比rand()低。
求解。。。
另外:我发现iteye的网站界面难看,编辑页设计也太差了。坑爹的提问积分制度。分数低了,没人愿意回答你。