We have often executed SQL queries of the type:
Did our update query fail ?
Or was the record with id 3 skipped as it was associated with a hibernate session ?
I decided to check the output in the database:
The query executed fine and updated all the records (including 3). So why does the persistent object continue to display the old data?
If we execute an SQL statement directly on the database then the statement result does not affect any objects in the persistence cache. Hibernate is not aware that Entity with id 3 has changed in the database. Hence it does update it and the entity continues to hold stale data.
Possible solutions to the problem would be:
update <table> set <record_column> = <value> where <condition>;These kind of queries that results in multiple records being updated are termed bulk updates.Hibernate allows us to do the same too. Consider the below code that updates the name column of all Entity records
static void testBulkUpdate() { Session session = sessionFactory.openSession(); Transaction transaction = null; try { transaction = session.beginTransaction(); Entity entity = (Entity) session.load(Entity.class, 3L); System.out.println("Entity name is " + entity.getName()); System.out.println("Updating all entity names "); Query query = session.createQuery("update Entity e set e.name = :newName"); query.setString("newName", "UNKNOWN"); query.executeUpdate(); transaction.commit(); System.out.println("Name of Entity with id " + entity.getId() + " is " + entity.getName() ); session.close(); } catch (Exception e) { e.printStackTrace(); transaction.rollback(); } }As seen in the above code the update query is written in HQL and executed Hibernate's Query Interface.The logs indicate the output of the code:
2406 [main] DEBUG org.hibernate.SQL - select entity0_.ID as ID0_0_, entity0_.NAME as NAME0_0_ from ENTITY entity0_ where entity0_.ID=? Entity name is Simple Name Updating all entity names 2812 [main] DEBUG org.hibernate.engine.query.HQLQueryPlan - HQL param location recognition took 15 mills (update Entity e set e.name = :newName) 2937 [main] DEBUG org.hibernate.engine.query.HQLQueryPlan - executeUpdate: upda te Entity e set e.name = :newName 2937 [main] DEBUG org.hibernate.SQL - update ENTITY set NAME=? 2953 [main] DEBUG org.hibernate.impl.SessionImpl - after transaction completion Name of Entity with id 3 is Simple NameAs can be seen a select query was executed initially which returns the entity with id 3 and displays the name property. After that the update query executes and this should update the name column for all records with value "UNKNOWN". After successful query execution we checked the value in persistent object Entity with id 3. However there is an anomaly here. The entity continues to display the name as Simple Name.
Did our update query fail ?
Or was the record with id 3 skipped as it was associated with a hibernate session ?
I decided to check the output in the database:
The query executed fine and updated all the records (including 3). So why does the persistent object continue to display the old data?
If we execute an SQL statement directly on the database then the statement result does not affect any objects in the persistence cache. Hibernate is not aware that Entity with id 3 has changed in the database. Hence it does update it and the entity continues to hold stale data.
Possible solutions to the problem would be:
- call session.refresh(entity) method. This would reload the row from the database. But then we would need to know precisely which row was affected.
- Execute all such bulk operations in the beginning of the session, ensuring that the persistence cache has no objects in it that could get affected by the update call.
No comments:
Post a Comment