[英]How to persist a lot of entities (JPA)
我需要处理一个CSV文件,并且每个记录(行)都会保留一个实体。 现在,我这样做:
while ((line = reader.readNext()) != null) {
Entity entity = createEntityObject(line);
entityManager.save(entity);
i++;
}
其中save(Entity)
方法基本上只是一个EntityManager.merge()
调用。 CSV文件中大约有20,000个实体(行)。 这是一种有效的方法吗? 这似乎很慢。 使用EntityManager.persist()
会更好吗? 这种解决方案是否有任何缺陷?
编辑
这是一个漫长的过程(超过400s),我尝试了两种解决方案, persist
和merge
。 两者的完成时间大致相同(459s vs 443s)。 问题是如果逐个保存实体是最佳的。 据我所知,Hibernate(我的JPA提供程序)确实实现了一些缓存/刷新功能,所以我不必担心这一点。
JPA API没有为您提供最佳选择。 根据您想要的速度,您将不得不寻找特定于ORM的选项 - 在您的情况下使用Hibernate。
要检查的事项:
所以在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特定的批量插入调整。
我认为这样做的一种常见方式是交易。 如果您开始新事务然后持久存储大量对象,则在提交事务之前,它们实际上不会插入到数据库中。 如果您要提交大量项目,这可以提高效率。
您可以使用经典的SQL Insert语句将它们直接写入数据库。
为了使它更快,至少在Hibernate中,你会在一定数量的插入后执行flush()和clear()。 我已经为数百万条记录做了这种方法并且它有效。 它仍然很慢,但它比不这样做要快得多。 基本结构是这样的:
int i = 0;
for(MyThingy thingy : lotsOfThingies) {
dao.save(thingy.toModel())
if(++i % 20 == 0) {
dao.flushAndClear();
}
}
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.