java - 大型 OpenJPA query.getResutList() 包装器以避免 List然后迭代
问题描述
版本openjpa-2.4.1=2.4.1.SNAPSHOT
我有一个复杂的 sql 作为 OpenJPA 中的本机查询运行。当循环遍历arraylist时,一些值过滤是在应用程序端完成的。
这意味着List<MyObject>
在将任何行写入 servlet 输出流之前保存在内存中。更不用说由于 mysql jdbc 驱动程序的工作方式,MySQL jdbc 结果集已完全读取到 RAM。因此,行在一段时间内被保存在 RAM 中两次。
调用函数时是否可以自定义渐进式行处理程序query.getResultList()
?我只能将有意义的 jdbc 行写入 json 响应并跳过那些不感兴趣的行。
或者有没有办法在应用程序端使用原始 jdbc 结果集并将行转换为 MyObject jpa 对象实例?它确实需要托管实例,但希望重用从 sql 到对象的现有序列化。
当前代码
Query query = em.createNativeQuery(sql, MyObject.class);
query.setParameter(1, "serverX");
List<MyObject> list=query.getResultList();
JsonGenerator jsonG = MyApplication.createJsonGenerator(providers, os);
jsonG.writeStartObject();
jsonG.writeFieldName("items");
jsonG.writeStartArray();
for(MyObject obj : list) {
if (obj.getType()==1) MyObject.writeJSONv1(jsong, obj);
else if (obj.getType()==2) MyObject.writeJSONv2(jsong, obj);
else if (obj.isValid() && obj.getType()==3) MyObject.writeJSONv3(jsong, obj);
else if (obj.getName().startsWith("abc")) MyObject.writeJSONvX(jsong, obj);
else Logger.log("Skipped " + obj.getId());
}
jsonG.writeEndArray();
jsonG.writeEndObject();
jsonG.flush();
jsonG.close();
伪代码,渐进式迭代器
Query query = em.createNativeQuery(sql, MyObject.class);
query.setParameter(1, "serverX");
Iterator iter=query.getCustomProgressiveRowIterator();
JsonGenerator jsonG = MyApplication.createJsonGenerator(providers, os);
jsonG.writeStartObject();
jsonG.writeFieldName("items");
jsonG.writeStartArray();
for(iter.hasNext()) {
MyObject obj = (MyObject)iter.next();
if (obj.getType()==1) MyObject.writeJSONv1(jsong, obj);
else if (obj.getType()==2) MyObject.writeJSONv2(jsong, obj);
else if (obj.isValid() && obj.getType()==3) MyObject.writeJSONv3(jsong, obj);
else if (obj.getName().startsWith("abc")) MyObject.writeJSONvX(jsong, obj);
else Logger.log("Skipped " + obj.getId());
}
jsonG.writeEndArray();
jsonG.writeEndObject();
jsonG.flush();
jsonG.close();
伪代码,将 jdbc 行转换为对象
PreparedStatement stmt = con.prepareStatement("Select * my complex query From MyObjects");
ResultSet rs = stmt.executeQuery();
while(rs.next()) {
// check few resultset fields, if all good then get MyObject
MyObject obj = OpenJPA.castResultSetToObject(rs);
MyObject.writeJSON(jsong, obj);
}
rs.close();
stmt.close();
编辑:@Gimby 有一条关于 getResultStream() 的评论,如果有一天 OpenJPA 有它,我将其链接到此处以供以后参考。还链接到 OpenJPA 3.x 票证。
https://www.thoughts-on-java.org/jpa-2-2s-new-stream-method-and-how-you-should-not-use-it/
https://issues.apache.org/ jira/浏览/OPENJPA-2711
解决方案
推荐阅读
- sql - 更新 SQL 错误:您输入的表达式引用了已关闭或不存在的对象
- c# - 具有不同生命周期的 Autofac 注册模块取决于应用程序(控制台或 Web)
- javascript - 将两个值都传递给 CSS 中的变量
- mysql-error-1066 - 我对这个查询有疑问,它说“不是唯一的表/别名'ownertbl'”我该怎么办?
- design-patterns - 构建聊天应用时混合使用Http和websockets的优缺点?
- r - 在分组数据框中选择具有共同 id 的行
- sql - oracle中sql输出的流程混乱
- antd - 在 antd 中使用字体 awsome
- python-3.x - Python:从包含打印到字符串变量的函数生成的输出
- python - 将列表的相似元素合并到一个新列表中