OutOfMemoryError:Java堆空间,同时使用Jdbctemplate检索数据:RowCallbackHandlerResultSetExtractor.extractData

问题描述

public List<Employee> getEmployeeDataByDate(Date dateCreated) throws Exception {
        List<Employee> listDetails = new ArrayList<>();
        
        sqlServTemplate.query(SyncQueryConstants.RETRIEVE_EMPLOYEE_RECORDS_BY_DATE,new Object[] { dateCreated },new RowCallbackHandler() {

                    @Override
                    public void processRow(ResultSet rs) throws sqlException {
                        Employee emp = new Employee();
                        emp.setEmployeeID(rs.getString("employeeID"));
                        emp.setFirstName(rs.getString("firstName"));
                        emp.setLastName(rs.getString("lastName"));
                        emp.setMiddleName(rs.getString("middleName"));
                        emp.setNickName(rs.getString("nickName"));

                        byte[] res = rs.getBytes("employeeImage");
                        Blob blob = new SerialBlob(res);
                        emp.setEmployeeImage(blob);

                        
                        // .....
                        
                        listDetails.add(emp);
                    }
                    
        });
        
        return listDetails;
    }

这里我正尝试检索employee表的记录。由于BLOB数据的原因,是说 OutOfMemoryError:Java堆空间。有人可以帮我吗?

这是一个独立的应用程序,我正在从一个表同步到另一个表。因此无法使用分页。每天2k记录将在午夜由cron作业同步。给我一些想法,我该如何解决这个问题。

SELECT * FROM Employees with(nolock) WHERE cast (datediff (day,dateCreated) as datetime) >= ?

查询根据日期为我提供了所有数据(每天约2k条记录)。 如果我要发表评论

byte[] res = rs.getBytes("employeeImage");
                        Blob blob = new SerialBlob(res);
                        emp.setEmployeeImage(blob);

此行则没有问题。否则,它会引发错误

请提供一些想法,如果可能,请提供一些示例代码。 我从这个工作的第二天开始苦苦挣扎。

解决方法

正如其他一些评论者所提到的,您可以增加堆空间或限制从查询中返回的记录数量,并分批处理它们。

,

您正在读取MB大小的图像(以字节为单位),它将占用您的HEAP内存。 而是尝试使用BinaryStream:

InputStream image = rs.getBinaryStream("employeeImage");
,

您可以将每个用户一次处理,而不是将每个用户添加到列表中。将每条记录从源数据库中拉出时,将其放在另一个数据库中,而不是将它们添加到导致OOM错误的列表中。如果下游还有其他处理,则将一个类注入此DAO中,以处理对目标DB的实际处理/写入。