我希望减少hibernate会话的开销(以提高性能,因为会话需要太多时间来处理其存储的对象)并尝试使用无状态会话:
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()。我还应该如何使用无状态会话以避免崩溃?
感谢名单。
答案 0 :(得分:0)
以下是documentation of the MySQL JDBC driver
的摘录默认情况下,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的所有可用内存。