如何保留大量实体(JPA)
问题内容:
我需要处理一个CSV文件,并且对于每个记录(行)都保留一个实体。现在,我这样做:
while ((line = reader.readNext()) != null) {
Entity entity = createEntityObject(line);
entityManager.save(entity);
i++;
}
该save(Entity)
方法基本上只是一个EntityManager.merge()
调用。CSV文件中大约有20,000个实体(行)。这是一种有效的方法吗?似乎很慢。使用会更好EntityManager.persist()
吗?这个解决方案有任何缺陷吗?
编辑
这是一个漫长的过程(超过400秒)和我都尝试的解决方案,与persist
和merge
。两者花费的时间大致相同(459s与443s)。问题是,像这样一个接一个地保存实体是否最佳。据我所知,Hibernate(这是我的JPA提供程序)确实实现了某些缓存/刷新功能,因此我不必为此担心。
问题答案:
JPA API并未为您提供最佳选择。根据您要执行此操作的速度,您将不得不寻找特定于ORM的选项-在您的情况下为休眠状态。
检查事项:
- 检查您是否正在使用单笔交易(是的,显然您对此有把握)
- 检查您的JPA提供程序(Hibernate)是否正在使用JDBC批处理API(请参阅:hibernate.jdbc.batch_size)
- 检查是否可以绕过获取生成的密钥(取决于db / jdbc驱动程序,您从中获得多少好处-请参阅:hibernate.jdbc.use_getGeneratedKeys)
- 检查您是否可以绕过级联逻辑(这样做只能带来最小的性能收益)
因此,在Ebean ORM中,这将是:
EbeanServer server = Ebean.getServer(null);
Transaction transaction = server.beginTransaction();
try {
// Use JDBC batch API with a batch size of 100
transaction.setBatchSize(100);
// Don't bother getting generated keys
transaction.setBatchGetGeneratedKeys(false);
// Skip cascading persist
transaction.setPersistCascade(false);
// persist your beans ...
Iterator<YourEntity> it = null; // obviously should not be null
while (it.hasNext()) {
YourEntity yourEntity = it.next();
server.save(yourEntity);
}
transaction.commit();
} finally {
transaction.end();
}
哦,如果您通过原始JDBC执行此操作,则会跳过ORM开销(减少了对象创建/垃圾收集等操作),因此我不会忽略该选项。
因此,是的,这不能回答您的问题,但可以帮助您搜索更多针对ORM的特定批量插入调整。