我正在尝试流式处理包含200m条记录的表。我进了大约70k,然后收到OutOfMemoryError。这是我的代码:
@Service
@Slf4j
public class Migrator {
@Autowired
LegacyDataRepository legacyDataRepository;
@Autowired
Producer producer;
@Transactional
public void run() {
AtomicInteger counter = new AtomicInteger(0);
try (Stream<Data> stream = legacyDataRepository.readAll()) {
stream.forEach(x -> {
try {
// the producer converts the data to json and writes to kafka
producer.send(data);
int currentCount = counter.incrementAndGet();
if (currentCount % 1000 == 0)
log.info("Migrated {} rows", currentCount);
} catch (JsonProcessingException e) {
log.error("Failed to send event", e);
}
});
}
}
}
这是我的存储库:
@Repository
@Slf4j
public class LegacyDataRepository {
@PersistenceContext
private EntityManager em;
public Stream<Data> readThreats() {
return em.createNativeQuery(query, Data.class)
.setHint(QueryHints.HINT_READONLY, true)
.setHint(QueryHints.HINT_FETCH_SIZE, 50 )
// .setFirstResult(0)
// .setMaxResults(1000)
.getResultStream();
}
}
在其他示例中,我发现这似乎是如何流式传输大表的整体。
EDIT1:
我怀疑@Transactional
保留了流中正在读取的所有记录。我添加了对EntityManager
的引用,并添加了em.clear();
,以保持对内存的检查。我真的很想解决这个更好的方法。
如何在不保留实体管理器中的实体的情况下读取流?