This article describes the method of hibernate batch operation. Share it for your reference, as follows:
Hibernate batch processing
Hibernate operates the database completely in an object-oriented way. When a persistent object is operated in an object-oriented way in the program, it will be automatically converted into an operation on the database. For example, when calling Session's delete() method to delete a persistent object, Hibernate will be responsible for deleting the corresponding data records; when executing the set method of the persistent object, Hibernate will automatically convert to the corresponding update method and modify the corresponding records of the database.
The question is if 100,000 records need to be updated at the same time, do you need to load 100,000 records one by one, and then call the set method in turn - this is not only cumbersome, but also the performance of data access is very bad. For this batch processing scenario, Hibernate provides a batch processing solution. The following introduces how to face this batch processing situation from three aspects: batch insertion, batch update and batch deletion.
1 Batch Insert
If you need to insert 100,000 records into the database, Hibernate may usually use the following:
Session session = sessionFactory.openSession();Transaction tx = session.beginTransaction();for ( int i=0; i<100000; i++ ) { User u = new User (......); session.save(customer);}tx.commit();session.close();But as this program runs, it will always fail at some point and an OutOfMemoryException is thrown. This is because Hibernate's Session holds a required level 1 cache, and all User instances will be cached in the Session-level cache area.
To solve this problem, there is a very simple idea: regularly refresh the data cached by the Session into the database, rather than always cache it at the Session level. You can consider designing an accumulator, which increases by 1 for each User instance saved. Determine whether the data in the Session cache needs to be flushed into the database based on the accumulator value.
Here is a snippet of code that adds 100,000 User instances:
private void testUser()throws Exception{ //Open Session Session session = HibernateUtil.currentSession(); //Start transaction Transaction tx = session.beginTransaction(); //Loop 100 000 times and insert 100 000 records for (int i = 0 ; i < 1000000 ; i++ ) { //Create User instance User u1 = new User(); u1.setName("xxxxx" + i); u1.setAge(i); u1.setNationality("china"); //Cach the User instance session.save(u1); //Whenever the accumulator is a multiple of 20, flush the data in the Session into the database and clear the Session cache if (i % 20 == 0) { session.flush(); session.clear(); tx.commit(); tx = session.beginTransaction(); } } //Commit transaction tx.commit(); //Close transaction HibernateUtil.closeSession();}In the above code, when i%20 == 0, the cached data at the Session is manually written to the database and the transaction is manually submitted. If the transaction is not submitted, the data will still be cached in the transaction office - it has not entered the database, which will also cause an exception of memory overflow.
This is the processing of Session-level cache, and the SessionFactory's secondary cache should also be turned off through the following configuration.
hibernate.cache.use_second_level_cache false
Note: In addition to manually clearing the Session-level cache, it is best to turn off the SessionFactory-level secondary cache. Otherwise, even if the Session-level cache is manually cleared, an exception may be thrown because there is still a cache at the SessionFactory level.
2 batch updates
The method described above is also suitable for batch update data. If you need to return multiple rows of data, you can use the scroll() method to make full use of the performance advantages brought by server-side cursors. Here is a code snippet for batch updates:
private void testUser()throws Exception{ //Open Session Session session = HibernateUtil.currentSession(); //Start the transaction Transaction tx = session.beginTransaction(); //Query all records in the User table ScrollableResults users = session.createQuery("from User") .setCacheMode(CacheMode.IGNORE) .scroll(ScrollMode.FORWARD_ONLY); int count=0; //Transaction all records in the User table while ( users.next() ) { User u = (User) users.get(0); u.setName("new username" + count); //When count is a multiple of 20, flush the updated result from the Session to the database if (++count % 20 == 0 ) { session.flush(); session.clear(); } } tx.commit(); HibernateUtil.closeSession();} In this way, although batch updates can be performed, the effect is very poor. The execution efficiency is not high, and data query is required first, and then data update is performed. This update will be a row-by-line update, that is, every time a row of records is updated, an update statement needs to be executed, and the performance is very low.
To avoid this, Hibernate provides an HQL syntax similar to SQL for batch updates and batch deletion.
3 SQL-style batch update/deletion
The HQL statements provided by Hibernate also support batch UPDATE and DELETE syntax.
The syntax format of batch UPDATE and DELETE statements is as follows:
UPDATE | DELETE FROM? ClassName [WHERE WHERE_CONDITIONS]
There are four points worth noting about the above syntax format:
● In the FROM clause, the FROM keyword is optional. That is, you can not write FROM keywords at all.
● There can only be one class name in the FROM clause, and the class name cannot have an alias.
● You cannot use connections in batch HQL statements, neither explicit nor implicit. But subqueries can be used in the WHERE clause.
● The entire WHERE clause is optional.
Assuming that you need to batch change the name attribute of the User class instance, you can use the following code snippet:
private void testUser()throws Exception{ //Open Session Session session = HibernateUtil.currentSession(); //Start transaction Transaction tx = session.beginTransaction(); //Define batch update HQL statement String hqlUpdate = "update User set name = :newName"; //Execute update int updatedEntities = session.createQuery( hqlUpdate ) .setString( "newName", "new name" ) .executeUpdate(); //Commit transaction tx.commit(); HibernateUtil.closeSession();}As can be seen from the above code, this syntax is very similar to the executeUpdate syntax of PreparedStatement. In fact, this batch update of HQL is directly borrowing from the UPDATE statement of SQL syntax.
Note: When using this batch update syntax, you usually only need to execute SQL UPDATE statement once to complete all updates that meet the conditional records. But it may also be necessary to execute multiple UPDATE statements, because there are special cases such as inheritance mapping, such as there is a Person instance, which has a subclass instance of Customer. When batch updates Person instances, the Customer instance also needs to be updated. If you use the joined-subclass or union-subclass mapping strategy, Person and Customer instances are saved in different tables, so multiple UPDATE statements may be required.
Execute an HQL DELETE, and use the Query.executeUpdate() method. The following is a code snippet that deletes all records above at once:
private void testUser() throws Exception{ //Open Session instance Session session = HibernateUtil.currentSession(); //Start transaction Transaction tx = session.beginTransaction(); //Define batch deletion HQL statement String hqlUpdate = "delete User"; //Execute batch deletion int updatedEntities = session.createQuery( hqlUpdate ) .executeUpdate(); //Commit transaction tx.commit(); //Close Session HibernateUtil.closeSession();}Returns an integer value by the Query.executeUpdate() method, which is the number of records affected by this operation. In fact, Hibernate's underlying operations are done through JDBC. Therefore, if there are batches of UPDATE or DELETE operations that are converted into multiple UPDATE or DELETE statements, the method returns the number of records affected by the last SQL statement.
I hope that the description in this article will be helpful to everyone's Java programming based on the Hibernate framework.