Hibernate中的批处理,实质上是对JDBC的批处理进行配置
要使用批处理插入数据,id生成策略不能是native策略,可以是uuid或者hilo
批量数据获取
属性:hibernate.jdbc.fetch_size
*MYSQL不支持,ORACLE支持
批量数据提交(极大的提高了批量执行的效率)
属性:hibernate.jdbc.batch_size
*MYSQL支持,ORACLE支持
步骤(理解):
1.id生成策略不能是native
[native依赖数据库生成id,每save()就会执行插入,否则无法生成id,所以无法进行批量插入]
可选策略:uuid/hilo 在内存中生成id,这样才能在commit的时候进行批量提交操作
2.关闭二级缓存,否则对象都被放入二级缓存中,有可能造成内存溢出,另外还影响速度
3.hibernate.cfg.xml中配置batch_size参数
4.MYSQL数据库需要修改url,加上 rewriteBatchedStatements=true
5.即时flush clear [及时清除一级缓存中的数据,每插入多少条记录便清除一次]
6.为了不影响批量插入的速度,关闭sql打印<property name="show_sql">false</property>
7.<property name="hibernate.jdbc.batch_size">50</property>
每50条进行一次批量插入,然后根据此参数在程序中定义清空缓存的时机
可设置为50的倍数,那么每插入4次后,就清空一次缓存,防止内存溢出
if(i%200==0) {
session.flush();//强制将内存中的持久化对象更新到数据库中
session.clear();//清空缓存中的持久化对象,防止内存溢出
}
package org.leadfar.hibernate.model;
import java.util.Date;
public class ContactPerson {
private int id;
private String name;
private int age;
private Date birthday;
private Group group;
private int versionNumber;
public ContactPerson() {
}
public ContactPerson(String name) {
this.name = name;
}
public ContactPerson(int id,String name) {
this.id = id;
this.name = name;
}
public ContactPerson(int id,int age,String name) {
this.id = id;
this.age = age;
this.name = name;
}
public int getId() {
return id;
}
public void setId(int id) {
this.id = id;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public Group getGroup() {
return group;
}
public void setGroup(Group group) {
this.group = group;
}
public int getAge() {
return age;
}
public void setAge(int age) {
this.age = age;
}
public Date getBirthday() {
return birthday;
}
public void setBirthday(Date birthday) {
this.birthday = birthday;
}
public int getVersionNumber() {
return versionNumber;
}
public void setVersionNumber(int versionNumber) {
this.versionNumber = versionNumber;
}
}
<?xml version="1.0"?>
<!DOCTYPE hibernate-mapping PUBLIC
"-//Hibernate/Hibernate Mapping DTD 3.0//EN"
"http://hibernate.sourceforge.net/hibernate-mapping-3.0.dtd">
<hibernate-mapping
package="org.hibernate.auction">
<class name="org.leadfar.hibernate.model.ContactPerson" table="t_person">
<id name="id">
<!-- 批量插入数据,可以使用hilo策略(不依赖数据库生成id值)-->
<generator class="hilo"/>
</id>
<!-- 版本标识,用于解决并发访问 -->
<version name="versionNumber"></version>
<property name="name"/>
<property name="age"></property>
<property name="birthday" type="date"></property>
<many-to-one name="group" column="gid" fetch="join"></many-to-one>
</class>
</hibernate-mapping>
测试
public void save_person() throws Exception {
Configuration cfg = new Configuration().configure();
SessionFactory sfactory = cfg.buildSessionFactory();
long begin = System.currentTimeMillis();
Session session = sfactory.openSession();
try {
session.beginTransaction();
for(int i=0;i<100000;i++) {
ContactPerson cp = new ContactPerson();
cp.setAge(1);
cp.setName("x");
session.save(cp);
if(i%200==0) {
session.flush();
session.clear();
}
}
session.getTransaction().commit();
} catch(Exception e) {
e.printStackTrace();
session.getTransaction().rollback();
} finally {
session.close();
}
long end = System.currentTimeMillis();
System.out.println("耗时:"+(end-begin)+"ms");
}