我要求在3个表中插入/更新超过15000行。这就是45k的总插入量。
我在网上阅读之后在休眠中使用了Statelesssession,因为它没有上下文缓存,所以它最适合批量处理。
session = sessionFactory.openStatelessSession;
for(Employee e: emplList) {
session.insert(e);
}
transcation.commit;
但是这段代码需要一个多小时才能完成。
有没有办法一次性保存所有实体对象? 保存整个集合而不是逐个进行?
编辑:还有其他框架可以提供快速插入吗?
干杯!!
答案 0 :(得分:1)
你应该阅读Vlad Mihalcea的这篇文章:
答案 1 :(得分:1)
您需要确保已设置hibernate属性:
hibernate.jdbc.batch_size
因此Hibernate可以批量处理这些插入,否则它们将一次完成一次。
答案 2 :(得分:1)
无法一次性插入所有实体。即使你可以在内部执行类似session.save(emplList)
的操作,Hibernate也会逐一保存。
因此,Hibernate用户指南StatelessSession不使用批处理功能:
StatelessSession接口定义的insert(),update()和delete()操作直接在数据库行上运行。它们导致相应的SQL操作立即执行。它们与Session接口定义的save(),saveOrUpdate()和delete()操作具有不同的语义。
而是使用普通会话并不时清除缓存。实际上,我建议您首先测量代码,然后进行更改,例如使用hibernate.jdbc.batch_size
,这样您就可以看到任何调整都增加了您的负载。
尝试改变它:
session = sessionFactory.openSession();
int count = 0;
int step = 0;
int stepSize = 1_000;
long start = System.currentTimeMillis();
for(Employee e:emplList) {
session.save(e);
count++;
if (step++ == stepSize) {
long elapsed = System.currentTimeMillis() - start;
long linesPerSecond = stepSize / elapsed * 1_000;
StringBuilder msg = new StringBuilder();
msg.append("Step time: ");
msg.append(elapsed);
msg.append(" ms Lines: ");
msg.append(count);
msg.append("/");
msg.append(emplList.size());
msg.append(" Lines/Seconds: ");
msg.append(linesPerSecond);
System.out.println(msg.toString());
start = System.currentTimeMillis();
step = 0;
session.clear();
}
}
transcation.commit;
关于hibernate.jdbc.batch_size
- 您可以尝试不同的值,包括一些非常大的值,具体取决于使用的基础数据库和网络配置。例如,对于应用服务器和数据库服务器之间的1gbps网络,我使用10,000的值,每秒给我20,000条记录。
将stepSize
更改为hibernate.jdbc.batch_size
的相同值。