有时候我们要一次插入大量数据到数据库中,比如10000条。但是,如果直接用 Play 框架常用的 Model.save() 方法循环插入,那么相当于操作了10000次数据库,执行会非常慢!例如下面的代码:
package util;
import models.finance.BalanceRecordModel;
import java.util.Date;
/**
* Created with IntelliJ IDEA.
*/
public class BalanceUtil {
// 按月份对账
public static Boolean excute(String period) throws Exception {
// 保存数据
for (int i = 0; i < 10000; i++) {
BalanceRecordModel record = new BalanceRecordModel();
record.balanceAt = new Date();
record.save();
}
return true;
}
}
为了极大的减少数据库的访问,我们使用 JPA.em().flush()
和 JPA.em().clear()
方法控制数据库的访问,比如每500条数据插入到数据库一次,这样10000条数据库只用访问 20 次数据库。代码参考如下:
package util;
import models.finance.BalanceRecordModel;
import java.util.Date;
/**
* Created with IntelliJ IDEA.
*/
public class BalanceUtil {
// 按月份对账
public static Boolean excute(String period) throws Exception {
// 保存数据
for (int i = 0; i < 10000; i++) {
BalanceRecordModel record = new BalanceRecordModel();
record.balanceAt = new Date();
record.save();
// 每500条提交到数据库一次
if (i % 500 == 0) {
Logger.info(">>>>>>>>>>>>>>>>>>>>>>>flush");
JPA.em().flush();
JPA.em().clear();
}
}
return true;
}
}
说明:
play 会自动管理事务。当 http 请求到达,play 就会为每个 http 请求启动一个事务。当 http response 发送的时候,就会把事务提交。如果代码抛出异常,事务将会自动回滚。所有不需要使用
JPA.em().getTransaction().begin()
和JPA.em().getTransaction().commit()
方法来手动控制事务。也不用使用@NoTransaction
注释来关闭事务,保持默认的事务机制就可以了。
评论
caca 11月09日 18:03
可以用wireshark抓包看下,只是批量commit,并非所说的”这样10000条数据库只用访问 20 次数据库“