Implementing bulk operations in Hibernate applications
In a recent project, when making a query, the need to bulk update the data, and then in the query.
In the Hiberante application, this update operation
One, Session.update (object)
One way to do this is to load a list according to a condition, and if there are tens or more of them, load so many objects into the Sessin cache
Then iterate over, updating each object one by one. When a transaction commits, it cleans up the cache while executing tens of thousands of update statements
Code tx = Session.begintransaction (); iterator Objects =session.find ("from Project where p.id>0"). iterator (); while (objects. Hasnext ()) {object object= (Object) objects. Next (); object.setxxx (); }tx.commit (); session.close ();
The above batch update method has two disadvantages:
(1) Consumes a lot of memory, you must load all eligible objects into memory first, and then update them all.
(2) The number of UPDATE statements executed is too large, each UPDATE statement can only update a customer object, frequent access to the database, will reduce the performance of the application.
to quickly release the memory occupied by an object, you can immediately release its memory by calling the session's evict () method after each object is updated:
Code tx = Session.begintransaction (); Iterator Objects=session.find ("hql"). iterator (); while (Objects.hasnext ()) {object = (object) objects.next (); Object.setxxx (); Session.flush (); Session.evict (customer); } tx.commit (); Session.close ();
The flush () method enables the hibernate to update the database immediately based on the state change of the object, executing the associated UPDATE statement, and the evict () method is used to purge the object from the cache, thereby releasing the memory it occupies in time.
Can slightly improve performance, but still produce tens of thousands of update statements, which affect the bulk operation of the important factors.
Ii. Direct execution of SQL
If hibernate can execute an UPDATE statement, the eligible objects will be updated at once.
However, hibernate does not directly provide an interface to execute this UPDATE statement. The application must bypass the Hibernate API and execute the SQL statement directly through the JDBC API:
Code tx = Session.begintransaction (); Connection con=session.connection (); PreparedStatement stmt=con.preparestatement (sql "); Stmt.executeupdate (); Tx.commit ();
The above program demonstrates the process of bypassing the Hibernate API and accessing the database directly through the JDBC API. The application obtains the database connection used by the session through the connection () method of the session, and then creates the PreparedStatement object and executes the SQL statement through it. It is noteworthy that the application still declares the transaction boundary through the Hibernate transaction interface.
Iii. use of stored procedures
If the underlying database, such as Oracle, supports stored procedures, you can also perform bulk updates through stored procedures. Stored procedures run directly in the database and are faster.
Code create or replace procedure updateproject is begin update project p set p.total_intend_gather = ( Select sum (ig.gather_sum) from intend_gather ig where ig.project_number= P.project_number); update project p set p.total_actual_gather = (select sum (ag.gahter_sum) from actual_gather ag where ag.project_number=p.project_number); update project p set p.total_invoice= (Select sum (invoice.invoice_sum) from invoice invoice where invoice.intend_id in (select ig.intend_id from intend_gather ig where ig.project_number=p.project_number)); end updateproject;
Calling code Code session = This.getsession (); Transaction TX =null; try {tx = Session.begintransaction (); Connection con = session.connection (); String procedure = "{Call Updateproject ()}"; CallableStatement cstmt = Con.preparecall (procedure); Cstmt.executeupdate (); Tx.commit (); catch (Exception e) {tx.rollback (); }
The above program shows that the application must also bypass the Hibernate API to invoke the stored procedure directly through the JDBC API.
Four, delete operation
The update () method of the various overloaded forms of the session can update only one object at a time, while some overloaded forms of the Delete () method allow HQL statements as arguments, such as:
Code Session.delete (from Project where p.id>0);
Able to implement bulk deletion, but it is disappointing that the session's delete () method does not execute the following DELETE statement
Code Delete from PROJECT where id>0;
But
The session's Delete () method loads all conforming objects into memory first through the following SELECT statement:
Code SELECT * FROM Project where id>0;
Next, execute n multiple DELETE statements, deleting the project object one by one:
Code Delete from PROJECT where id=i; Delete from PROJECT where id=j; Delete from PROJECT where id=k;
Therefore, the direct through the Hibernate API for batch updates and bulk deletion is not happy. Using the JDBC API directly to execute related SQL statements or call related stored procedures is the best way to batch update and bulk Delete, both of which have the following advantages:
(1) Do not need to load the bulk of the data in the database into memory, and then update or modify them individually, so do not consume a lot of memory.
(2) can update or delete large quantities of data in an SQL statement.