0

我想减少休眠会话的开销(以提高性能,因为会话需要太多时间来处理其存储的对象)并尝试使用无状态会话:

            statelessSession.createQuery(
                    "SELECT me, me.mailSourceFile, me.linf " +
                            "FROM MessageEntry me " +
                            "WHERE me.mailSourceFile.archive.folder = :folder " +
                            "ORDER BY me.messageLength DESC")
                    .setString("folder", folder)
                    .scroll(ScrollMode.FORWARD_ONLY);

但是 .scroll(...) 给出

Exception in thread "main" java.lang.OutOfMemoryError: Java heap space
    at com.mysql.jdbc.Buffer.<init>(Buffer.java:59)
    at com.mysql.jdbc.MysqlIO.nextRow(MysqlIO.java:1477)
    at com.mysql.jdbc.MysqlIO.readSingleRowSet(MysqlIO.java:2936)
    at com.mysql.jdbc.MysqlIO.getResultSet(MysqlIO.java:477)

...

我的代码没有 memleaks,它可以与 Session 和 .iterator() 一起正常工作。我还应该如何使用无状态会话来避免崩溃?

谢谢。

4

1 回答 1

0

这是 MySQL JDBC 驱动程序文档的摘录

默认情况下,ResultSet 被完全检索并存储在内存中。在大多数情况下这是最有效的操作方式,并且由于 MySQL 网络协议的设计更容易实现。如果您正在使用具有大量行或大值的 ResultSet,并且无法在 JVM 中为所需的内存分配堆空间,您可以告诉驱动程序一次将结果流回一行。

要启用此功能,请按以下方式创建 Statement 实例:

stmt = conn.createStatement(java.sql.ResultSet.TYPE_FORWARD_ONLY,
                            java.sql.ResultSet.CONCUR_READ_ONLY);
stmt.setFetchSize(Integer.MIN_VALUE);

只进、只读结果集与 Integer.MIN_VALUE 提取大小的组合用作驱动程序逐行流式传输结果集的信号。在此之后,将逐行检索使用该语句创建的任何结果集。

这种方法有一些注意事项。您必须先读取结果集中的所有行(或将其关闭),然后才能对连接发出任何其他查询,否则将引发异常。

假设您在从 MySQL 结果集读取时得到 OutOfMemoryError,我的猜测是这个结果集完全在内存中读取,并且大到足以消耗 JVM 的所有可用内存。

于 2013-08-11T21:01:31.950 回答