Hibernate查詢之Criteria查詢in中的長度大於1000解決方案
阿新 • • 發佈:2018-12-31
眾所周知。hibernate的查詢有好幾種,Criteria正是其查詢方式的一種,跟其他查詢方式比較下具體優缺多有爭議,不過這個不是今天要討論的重點,我開發用的就是Criteria查詢,先來說說我在使用中遇到的問題,在查詢中對於in的使用我想都很普遍,比如:
Criteria createCriteria = this.getHibernateSession().createCriteria(
VideoQualitBadGpsPoint.class);
createCriteria .add(Restrictions.in("id", list));
然而這樣問題就來了,對於in中的集合會有一個長度限制,當集合長度大於1000的時候會報錯,那麼問題來了,在查詢中in後的集合大於1000是很常見的,總不能一次查詢要手動拆分成多個查詢再拼接結果巴,當然這樣是可以的,不過效率太低,於是研究了一個解決方案如下:
這裡主要的就是Disjunction的引入,可以拼接多個in,相當於SQL中的in()or in() or in().....public List<VideoQualitBadGpsPoint> getVideoQualityBadGpsPointsByIds( List<VideoQualityBad> videoQualityBads) { List<VideoQualitBadGpsPoint> points = new ArrayList<>(); if (null == videoQualityBads || 0 == videoQualityBads.size()) { return points; } ArrayList<Long> idList = new ArrayList<Long>(); for (VideoQualityBad videoQualityBad : videoQualityBads) { idList.add(videoQualityBad.getId()); } Criteria createCriteria = this.getHibernateSession().createCriteria( VideoQualitBadGpsPoint.class); Criteria criteria = createCriteria.createCriteria("videoQualityBad"); if (idList.size() > 1000) { Disjunction dis = Restrictions.disjunction(); List<List<Long>> segmentationList = segmentationList(idList, 999); for (List<Long> list : segmentationList) { dis.add(Restrictions.in("id", list)); } criteria.add(dis); } else { criteria.add(Restrictions.in("id", idList)); } createCriteria.add(Restrictions.eq("gpsPointType", 0)); // latitude 16.585919~53.743108 // longitude 73.386567~135.300369 // 篩選經緯度 // 篩選經緯度 createCriteria.add(Restrictions.between("latitude", Float.valueOf("16.585919"), Float.valueOf("53.743108"))); createCriteria.add(Restrictions.between("longitude", Float.valueOf("73.386567"), Float.valueOf("135.300369"))); createCriteria.add(Restrictions.neOrIsNotNull("gpsPointTime", 0l)); createCriteria.addOrder(Order.asc("gpsPointTime")); points = criteria.list(); return points; } /** * 分割List * * @param targe * @param size * @return */ public static List<List<Long>> segmentationList(List<Long> targe, int size) { List<List<Long>> listArr = new ArrayList<List<Long>>(); // 獲取被拆分的陣列個數 int arrSize = targe.size() % size == 0 ? targe.size() / size : targe .size() / size + 1; for (int i = 0; i < arrSize; i++) { List<Long> sub = new ArrayList<Long>(); // 把指定索引資料放入到list中 for (int j = i * size; j <= size * (i + 1) - 1; j++) { if (j <= targe.size() - 1) { sub.add(targe.get(j)); } } listArr.add(sub); } return listArr; }
當然網上可能有更多更好的解決方案,這種只是我個人研究得出,僅供參考