Hibernate 批量插入的测试:
最近在项目中做了一个充值卡的模块,用到了批量插入:我一开始用hibernate插入五十万条数据:选说一下我的记算机配置:
内存:1G,CPU:Pentium(R) 4 CPU 3.20GHz. 配置应该算是过时的了,
我的数据库是:oracle10G,数据库服务器在外地,我测试插入到十万条的时候用了二十五分钟,后来我把程序放到外网服务器:配置:酷睿2代 2.0,4G内存,
插入十万条是五分钟,速试是大大的提升,但是我还是感觉有点慢,后来我用JDBC的批处理:还是在我本地插入:10万条用时:不到1分钟,如果放到外网服务器就更快。
下面贴一下我的代码:hibernate批量导入代码:(只是部分代码,不能运行。)
public boolean addCardList( final SysCardImport sysCardImport,final Date date){
boolean bool =(Boolean) hibernateTemplate.execute(new HibernateCallback() {
public Object doInHibernate(Session session) throws HibernateException, SQLException {
boolean flag=true;
try {
int i=0;
String temp=sysCardImport.getCardSymbol(); //卡代号
SimpleDateFormat sdf=new SimpleDateFormat("yyyy-MM-dd");
//取得充值卡类型值和面额值
SysPublictype cardType = (SysPublictype)session.get(SysPublictype.class, sysCardImport.getCardType());
SysPublictype cardMoney = (SysPublictype)session.get(SysPublictype.class, sysCardImport.getCardMoney());
temp+=cardType.getVchvalue();
temp+=cardMoney.getVchvalue();
String templeng[]=sysCardImport.getPasswordChar();
for(int len=0;len<templeng.length;len++){ //循环遍历充值卡加密字符串
String temparray[]=templeng[len].split(":");
String temps=temp+temparray[0]; //加密字符串代码
long cardnum=0;
List list= session.createQuery(" from SysCard t where t.vchcode like ? order by t.vchcode desc")
.setString(0, ""+temps+"%").list();
if(list.size()>0){
SysCard card=(SysCard)list.get(0);
cardnum = Long.valueOf(card.getVchcode().substring(10));
}
for(int num=0;num<sysCardImport.getCardAmount();num++){ //生成充值卡卡号
String cardroand="000000000"+(++cardnum);
cardroand=cardroand.substring(cardroand.length()-10);
SysCard sysCard=new SysCard();
SysPassword sysPassword=new SysPassword();
String password=BJFYSystemUtil.getRandomString(sysCardImport.getCardPasswordLength(),2);
sysCard.setVchcode(temps+cardroand);
sysCard.setNummoney(sysCardImport.getCardMoneys());
sysCard.setCstate("10");
sysCard.setDatcreate(date);
sysCard.setDatavailability(sdf.parse(sysCardImport.getCardDate()));
sysCard.setVchremark(sysCardImport.getCardRemark());
sysCard.setVchpassword(BJFYSystemUtil.getMD5(password+temparray[1]));
sysCard.setNumscale(sysCardImport.getCardScale());
sysCard.setVarkey(temparray[1]);
sysCard.setVchtype(cardType.getId());
sysPassword.setVchcode(temps+cardroand);
sysPassword.setVchpassword(password);
sysPassword.setVchpasschar(temparray[1]);
session.save(sysPassword);
session.save(sysCard);
if ((i + 1) % 1000 == 0) {
session.flush();
session.clear();
}
i++;
}
}
} catch (Exception e) {
log.error(e);
e.printStackTrace();
flag = false;
}
return flag;
}
});
return bool;
}
下面是JDBC批处理的代码:
public boolean addCardListByJdbc( final SysCardImport sysCardImport,final Date date){
boolean flag=true;
Connection con= this.hibernateTemplate.getSessionFactory().openSession().connection();
PreparedStatement stm=null;
PreparedStatement stm2=null;
try {
int i=0;
String temp=sysCardImport.getCardSymbol(); //卡代号
SimpleDateFormat sdf=new SimpleDateFormat("yyyy-MM-dd");
//取得充值卡类型值和面额值
SysPublictype cardType = (SysPublictype)hibernateTemplate.get(SysPublictype.class, sysCardImport.getCardType());
SysPublictype cardMoney = (SysPublictype)hibernateTemplate.get(SysPublictype.class, sysCardImport.getCardMoney());
temp+=cardType.getVchvalue();
temp+=cardMoney.getVchvalue();
con.setAutoCommit(false);
stm=con.prepareStatement("insert into sys_card values(?,?,?,?,?,?,?,?,?,?)");
stm2=con.prepareStatement("insert into sys_password values(?,?,?)");
String templeng[]=sysCardImport.getPasswordChar();
for(int len=0;len<templeng.length;len++){ //循环遍历充值卡加密字符串
String temparray[]=templeng[len].split(":");
String temps=temp+temparray[0]; //加密字符串代码
long cardnum=0;
List list= hibernateTemplate.find(" from SysCard t where t.vchcode like ? order by t.vchcode desc", temps+"%");
if(list.size()>0){
SysCard card=(SysCard)list.get(0);
cardnum = Long.valueOf(card.getVchcode().substring(10));
}
for(int num=0;num<sysCardImport.getCardAmount();num++){ //生成充值卡卡号
String cardroand="000000000"+(++cardnum);
cardroand=cardroand.substring(cardroand.length()-10);
SysCard sysCard=new SysCard();
SysPassword sysPassword=new SysPassword();
String password=BJFYSystemUtil.getRandomString(sysCardImport.getCardPasswordLength(),2);
stm.setString(1,temps+cardroand);
stm.setString(2, BJFYSystemUtil.getMD5(password+temparray[1]));
stm.setLong(3, sysCardImport.getCardMoneys());
stm.setLong(4, sysCardImport.getCardScale());
stm.setString(5,cardType.getId() );
stm.setDate(6, new java.sql.Date(System.currentTimeMillis()));
stm.setDate(7, new java.sql.Date(date.getTime()));
stm.setString(8, "10");
stm.setString(9, temparray[1]);
stm.setString(10, sysCardImport.getCardRemark());
stm.addBatch();
stm2.setString(1, temps+cardroand);
stm2.setString(2, password);
stm2.setString(3,temparray[1]);
stm2.addBatch();
if ((i + 1) % 1000 == 0) {
stm.executeBatch();
stm2.executeBatch();
con.commit();
}
i++;
}
}
if(stm!=null) {
stm.executeBatch();
stm2.executeBatch();
con.commit();
}
} catch (Exception e) {
log.error(e);
e.printStackTrace();
flag = false;
}finally{
try {
con.close();
stm=null;
stm2=null;
} catch (SQLException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
return flag;
}
综上所述,hibernate的批量更新和插入要创建和销毁大量的对象,尤其是带有复杂业务逻辑的,所以本人建议在大批量导入和更新时,最好使用JDBC的批处理.在批处理上hibernate和jdbc Batch不是一个等级的。