批处理
因为默认下,Hibernate 将缓存所有的在会话层缓存中的持久的对象并且最终你的应用程序将和 OutOfMemoryException 在第 50000 行的某处相遇。你可以解决这个问题,如果你在 Hibernate 使用批处理。
为了使用批处理这个特性,首先设置 hibernate.jdbc.batch_size 作为批处理的尺寸,取一个依赖于对象尺寸的值 20 或 50。这将告诉 hibernate 容器每 X 行为一批插入。为了在你的代码中实现这个我们将需要像以下这样做一些修改:
Transaction tx = session.beginTransaction();
for ( int i=0; i<100000; i++ ) {
Employee employee = new Employee(.....);
session.save(employee);
if( i % 50 == 0 ) { // Same as the JDBC batch size
//flush a batch of inserts and release memory:
session.flush();
session.clear();
}
}
tx.commit();
session.close();
让我们通过添加 hibernate.jdbc.batch_size 属性来修改配置文件:
<?xml version="1.0" encoding="utf-8"?>
<!DOCTYPE hibernate-configuration SYSTEM
"http://www.hibernate.org/dtd/hibernate-configuration-3.0.dtd">
<hibernate-configuration>
<session-factory>
<property name="hibernate.dialect">
org.hibernate.dialect.MySQLDialect
</property>
<property name="hibernate.connection.driver_class">
com.mysql.jdbc.Driver
</property>
<!-- Assume students is the database name -->
<property name="hibernate.connection.url">
jdbc:mysql://localhost/test
</property>
<property name="hibernate.connection.username">
root
</property>
</property>
<property name="hibernate.jdbc.batch_size">
50
</property>
<!-- List of XML mapping files -->
<mapping resource="Employee.hbm.xml"/>
</session-factory>
</hibernate-configuration>
考虑以下 POJO Employee 类:
create table EMPLOYEE (
id INT NOT NULL auto_increment,
first_name VARCHAR(20) default NULL,
last_name VARCHAR(20) default NULL,
salary INT default NULL,
PRIMARY KEY (id)
);
以下是将 Employee 对象和 EMPLOYEE 表单配对的映射文件。
最后,我们将用 main() 方法来创建我们的应用程序类以运行应用程序,我们将使用 Session 对象和可用的 flush() 和 clear() 方法以让 Hibernate 持续将这些记录写入数据库而不是在内存中缓存它们。
import java.util.*;
import org.hibernate.HibernateException;
import org.hibernate.Session;
import org.hibernate.Transaction;
import org.hibernate.SessionFactory;
import org.hibernate.cfg.Configuration;
public class ManageEmployee {
private static SessionFactory factory;
public static void main(String[] args) {
try{
factory = new Configuration().configure().buildSessionFactory();
}catch (Throwable ex) {
System.err.println("Failed to create sessionFactory object." + ex);
throw new ExceptionInInitializerError(ex);
/* Add employee records in batches */
ME.addEmployees( );
}
/* Method to create employee records in batches */
public void addEmployees( ){
Session session = factory.openSession();
Transaction tx = null;
Integer employeeID = null;
try{
tx = session.beginTransaction();
for ( int i=0; i<100000; i++ ) {
String fname = "First Name " + i;
String lname = "Last Name " + i;
Integer salary = i;
Employee employee = new Employee(fname, lname, salary);
session.save(employee);
if( i % 50 == 0 ) {
session.flush();
session.clear();
}
}
tx.commit();
}catch (HibernateException e) {
if (tx!=null) tx.rollback();
e.printStackTrace();
}finally {
session.close();
}
return ;
}
}
编译和执行
- 如上面解释的那样创建 hibernate.cfg.xml 配置文件。
- 如上面显示的那样创建 Employee.hbm.xml 映射文件。
- 如上面显示的那样创建 Employee.java 源文件并编译。
- 执行 ManageEmployee 二进制代码来运行可以在 EMPLOYEE 表单中创建 100000 个记录的程序。