gpt4 book ai didi

java - 使用 JdbcTemplate 获取和发送数百万条记录的最佳实践

转载 作者:太空宇宙 更新时间:2023-11-04 12:49:26 26 4
gpt4 key购买 nike

在我的 Web 应用程序中,用户可以编写自己的 sql 查询并创建数据集。我使用 Apache Camel 的 REST 组件和带有 JdbcTemplate 的 Spring JDBC 来执行查询。但是在执行查询时,返回大量记录(大约一百万条),抛出异常并显示以下堆栈跟踪:

org.apache.camel.CamelExecutionException: Exception occurred during execution on the exchange:...
.....
.....
Caused by: java.lang.OutOfMemoryError: Java heap space

以下是我用来查询数据库并发送响应的方法:

REST 端点

rest("/abc").consumes("application/json").produces("application/json")
.get("/xyz").to("bean:d?method=getXYZ(${body})").outTypeList(Map.class)

执行查询的方法:

public List<Map<String,Object>> getXYZ(Map<String,Object> details) {
JdbcTemplate jdbc=new JdbcTemplate(ds); //ds is DataSource Object

List<Map<String,Object>> resultSet=jdbc.query(details.get("query").toString(), new RowMapper<Map<String,Object>>() {

@Override
public Map<String, Object> mapRow(ResultSet rs, int rowNum) throws SQLException {
Map<String,Object> map = new HashMap<String,Object>();
DateFormat nice = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
ResultSetMetaData meta = rs.getMetaData();
for(int i = 1; i <= meta.getColumnCount(); ++i) {
Object o = rs.getObject(i);
if(o instanceof Date) {
o = nice.format(o);
}
//put into map.
map.put(meta.getColumnLabel(i), o);
}
return map;
}

});
return resultSet;
}

我尝试使用 jdbc.setFetchSize(1000) 设置获取大小,还尝试使用 -Xmx1024m -XX:MaxPermSize=1024m 增加堆内存,但无法解决。

查询、获取和发送如此大数据的响应的最佳实践是什么?

是什么导致了 java.lang.OutOfMemoryError ?

有没有办法在客户端压缩数据并自动解压?或流式传输结果集?

最佳答案

由于大量对象被加载到您的应用程序中,因此发生了 OutOfMemory。

让我们假设只加载 String 对象。 Java 每个字符存储 2 个字节,因此假设正在加载的所有字符串都是 5 个字符长。

让我们创建非常非常近似的计算。 5个字符的字符串对象是10个字节。其中 1000 个则大约为 10 KB,1000000 个则大约为 10 MB。

我假设你的对象不仅仅是 5 个字符串,所以你可以想象你的内存消耗得有多快。

我强烈建议您将用户限制为有限的行数并引入分页。因此,即使用户没有在 SQL 中输入限制和偏移量,我也会以编程方式添加,以避免此问题。

关于java - 使用 JdbcTemplate 获取和发送数百万条记录的最佳实践,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/35982140/

26 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com