转载

Hibernate批量处理

   

考虑这样一种情况,当需要使用Hibernate上传大量的记录到数据库中。以下是代码片段实现这一使用Hibernate:

 Session session = SessionFactory.openSession(); Transaction tx = session.beginTransaction(); for ( int i=0; i<100000; i++ ) {     Employee employee = new Employee(.....);     session.save(employee); } tx.commit(); session.close();

因为默认情况下,Hibernate会缓存所有的持久对象在session级别的缓存,并最终应用程序会失败并发生OutOfMemoryException某处50,000条记录左右。如果使用的是批量处理与Hibernate解决这个问题。

要使用批量处理功能,首先设置hibernate.jdbc.batch_size为批量大小若干无论是在20或50根据对象的大小。这将告诉每X行插入批次hibernate的容器。为了实现这个在代码中,我们需要做一点修改如下:

 Session session = SessionFactory.openSession(); 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();

上面的代码将正常工作INSERT操作,但如果愿意做UPDATE操作,那么可以使用下面的代码实现:

 Session session = sessionFactory.openSession(); Transaction tx = session.beginTransaction();  ScrollableResults employeeCursor = session.createQuery("FROM EMPLOYEE")                                    .scroll(); int count = 0;  while ( employeeCursor.next() ) {    Employee employee = (Employee) employeeCursor.get(0);    employee.updateEmployee();    seession.update(employee);     if ( ++count % 50 == 0 ) {       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 name="hibernate.connection.password">       root123    </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类:

 public class Employee {    private int id;    private String firstName;     private String lastName;       private int salary;       public Employee() {}    public Employee(String fname, String lname, int salary) {       this.firstName = fname;       this.lastName = lname;       this.salary = salary;    }    public int getId() {       return id;    }    public void setId( int id ) {       this.id = id;    }    public String getFirstName() {       return firstName;    }    public void setFirstName( String first_name ) {       this.firstName = first_name;    }    public String getLastName() {       return lastName;    }    public void setLastName( String last_name ) {       this.lastName = last_name;    }    public int getSalary() {       return salary;    }    public void setSalary( int salary ) {       this.salary = salary;    } }

让我们创建下面的EMPLOYEE表来存储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表的对象。

 <?xml version="1.0" encoding="utf-8"?> <!DOCTYPE hibernate-mapping PUBLIC   "-//Hibernate/Hibernate Mapping DTD//EN"  "http://www.hibernate.org/dtd/hibernate-mapping-3.0.dtd">   <hibernate-mapping>    <class name="Employee" table="EMPLOYEE">       <meta attribute="class-description">          This class contains the employee detail.        </meta>       <id name="id" type="int" column="id">          <generator class="native"/>       </id>       <property name="firstName" column="first_name" type="string"/>       <property name="lastName" column="last_name" type="string"/>       <property name="salary" column="salary" type="int"/>    </class> </hibernate-mapping>

最后,我们将创建与应用程序类main()方法来运行,我们将使用flush() 和 clear()可Session对象方法,使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);        }       ManageEmployee ME = new ManageEmployee();        /* 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 ;    } }

编译和执行:

下面是步骤来编译并运行上述应用程序。请确保您已在进行的编译和执行之前,适当地设置PATH和CLASSPATH。

  • 创建hibernate.cfg.xml配置文件,如上面所述。

  • 创建Employee.hbm.xml映射文件,如上图所示。

  • 创建Employee.java源文件,如上图所示,并编译它。

  • 创建ManageEmployee.java源文件,如上图所示,并编译它。

  • 执行ManageEmployee二进制运行将在EMPLOYEE表中创建100000条记录程序。

   
正文到此结束
Loading...