Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

using Hibernate to loading 20K products, modifying the entity and updating to db

I am using hibernate to update 20K products in my database.

As of now I am pulling in the 20K products, looping through them and modifying some properties and then updating the database.

so:

load products

foreach products
   session begintransaction
   productDao.MakePersistant(p);
   session commit();

As of now things are pretty slow compared to your standard jdbc, what can I do to speed things up?

I am sure I am doing something wrong here.

like image 702
Blankman Avatar asked Mar 07 '10 22:03

Blankman


People also ask

Which of the following method is used to save and update an entity in the database using Hibernate?

save() method does an INSERT to store the object into the database and return the identifier generated by the database. On the other hand, saveOrUpdate() can do INSERT or UPDATE depending upon whether object exists in database or not.

How do you update a record in hibernate?

We can update an object in hibernate by calling the update() method, provided by the org. hibernate. Session. Though the update() method is used to update an object, there are two different ways to use update() method.

How does update work in hibernate?

As with persist and save, the update method is an “original” Hibernate method. Its semantics differ in several key points: it acts upon a passed object (its return type is void). The update method transitions the passed object from a detached to persistent state.


1 Answers

The right place to look at in the documentation for this kind of treatment is the whole Chapter 13. Batch processing.

Here, there are several obvious mistakes in your current approach:

  • you should not start/commit the transaction for each update.
  • you should enable JDBC batching and set it to a reasonable number (10-50):

    hibernate.jdbc.batch_size 20
    
  • you should flush() and then clear() the session at regular intervals (every n records where n is equal to the hibernate.jdbc.batch_size parameter) or it will keep growing and may explode (with an OutOfMemoryException) at some point.

Below, the example given in the section 13.2. Batch updates illustrating this:

Session session = sessionFactory.openSession();
Transaction tx = session.beginTransaction();

ScrollableResults customers = session.getNamedQuery("GetCustomers")
    .setCacheMode(CacheMode.IGNORE)
    .scroll(ScrollMode.FORWARD_ONLY);
int count=0;
while ( customers.next() ) {
    Customer customer = (Customer) customers.get(0);
    customer.updateStuff(...);
    if ( ++count % 20 == 0 ) {
        //flush a batch of updates and release memory:
        session.flush();
        session.clear();
    }
}

tx.commit();
session.close();

You may also consider using the StatelessSession.

Another option would be to use DML-style operations (in HQL!): UPDATE FROM? EntityName (WHERE where_conditions)?. This the HQL UPDATE example:

Session session = sessionFactory.openSession();
Transaction tx = session.beginTransaction();

String hqlUpdate = "update Customer c set c.name = :newName where c.name = :oldName";
// or String hqlUpdate = "update Customer set name = :newName where name = :oldName";
int updatedEntities = s.createQuery( hqlUpdate )
        .setString( "newName", newName )
        .setString( "oldName", oldName )
        .executeUpdate();
tx.commit();
session.close();

Again, refer to the documentation for the details (especially how to deal with the version or timestamp property values using the VERSIONED keyword).

like image 200
Pascal Thivent Avatar answered Nov 14 '22 23:11

Pascal Thivent