我嘗試使用hibernate的可滾動結果從參考this github項目從數據庫中獲取記錄,我試圖發送每個記錄作爲塊響應。如何從表中讀取所有記錄(> 1000萬條記錄)並將每條記錄作爲組塊響應提供?
控制器:
@Transactional(readOnly=true)
public Result fetchAll() {
try {
final Iterator<String> sourceIterator = Summary.fetchAll();
response().setHeader("Content-disposition", "attachment; filename=Summary.csv");
Source<String, ?> s = Source.from(() -> sourceIterator);
return ok().chunked(s.via(Flow.of(String.class).map(i -> ByteString.fromString(i+"\n")))).as(Http.MimeTypes.TEXT);
} catch (Exception e) {
return badRequest(e.getMessage());
}
}
服務:
public static Iterator<String> fetchAll() {
StatelessSession session = ((Session) JPA.em().getDelegate()).getSessionFactory().openStatelessSession();
org.hibernate.Query query = session.createQuery("select l.id from Summary l")
.setFetchSize(Integer.MIN_VALUE).setCacheable(false).setReadOnly(true);
ScrollableResults results = query.scroll(ScrollMode.FORWARD_ONLY);
return new models.ScrollableResultIterator<>(results, String.class);
}
迭代:
public class ScrollableResultIterator<T> implements Iterator<T> {
private final ScrollableResults results;
private final Class<T> type;
public ScrollableResultIterator(ScrollableResults results, Class<T> type) {
this.results = results;
this.type = type;
}
@Override
public boolean hasNext() {
return results.next();
}
@Override
public T next() {
return type.cast(results.get(0));
}
}
對於測試的目的,我是ħ在我的表中有1007條記錄,每當我稱這個終點時,它總是隻返回503條記錄。
啓用AKKA日誌級別爲DEBUG並再次嘗試它,它會記錄以下行1007次 2016-07-25 19:55:38 +0530 [DEBUG] from org.hibernate.loader.Loader in application-akka.actor.default-dispatcher-73 - Result row:
從日誌中我確認它獲取所有內容,但無法獲取剩餘的剩餘內容。
我在我的工作臺中運行相同的查詢,並將其導出到本地文件,並將其與端點生成的文件進行比較,保留從端點生成的LHS記錄和從Workbench導出的RHS文件。 第一行匹配,第二個和第三個不匹配。之後,直到最後,它纔得到替代記錄的匹配。
請糾正我,如果我做錯了什麼,並建議我這是用於生成CSV大型數據庫記錄的正確的做法。
爲了測試的目的,我刪除了上面代碼片段中的CSV轉換邏輯。
接下來會有下一個呼叫。我會假設hasNext什麼也不做(即只檢查),而下一步推進內部光標? – rethab