項目中要求隨機取得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的網站界面難看,編輯頁設計也太差了。坑爹的提問積分制度。分數低了,沒人願意回答你。