Search This Blog

Thursday 8 September 2011

Save only those that need saving

When the application is started Hibernate will generate CRUD statements for all the mapped tables. For example, if consider the pet table (I have maintained the audit columns added in the previous post.) then from the logs we can see the following:
3719 [main] DEBUG org.hibernate.persister.entity.AbstractEntityPersister  - Stat
ic SQL for entity: com.menagerie.domain.entity.Pet
3719 [main] DEBUG org.hibernate.persister.entity.AbstractEntityPersister  -  Ver
sion select: select ID from PET where ID =? 
3719 [main] DEBUG org.hibernate.persister.entity.AbstractEntityPersister  -  Sna
pshot select: select pet_.ID, pet_.NAME as NAME1_, pet_.AGE as AGE1_, pet_.TAGID
 as TAGID1_, pet_.OWNER_ID as OWNER5_1_, pet_.MODIFIED_BY as MODIFIED6_1_, pet_.
CREATED_BY as CREATED7_1_ from PET pet_ where pet_.ID=?
3719 [main] DEBUG org.hibernate.persister.entity.AbstractEntityPersister  -  Ins
ert 0: insert into PET (NAME, AGE, TAGID, OWNER_ID, MODIFIED_BY, CREATED_BY, ID)
 values (?, ?, ?, ?, ?, ?, ?)
3719 [main] DEBUG org.hibernate.persister.entity.AbstractEntityPersister  -  Upd
ate 0: update PET set NAME=?, AGE=?, TAGID=?, OWNER_ID=?, MODIFIED_BY=?, CREATED
_BY=? where ID=?
3719 [main] DEBUG org.hibernate.persister.entity.AbstractEntityPersister  -  Del
ete 0: delete from PET where ID=?
3719 [main] DEBUG org.hibernate.persister.entity.AbstractEntityPersister  -  Ide
ntity insert: insert into PET (NAME, AGE, TAGID, OWNER_ID, MODIFIED_BY, CREATED_
BY) values (?, ?, ?, ?, ?, ?)
3719 [main] DEBUG org.hibernate.persister.entity.AbstractEntityPersister  - Inse
rt-generated property select: select pet_.CREATED_DATE as CREATED8_1_, pet_.MODI
FIED_DATE as MODIFIED9_1_ from PET pet_ where pet_.ID=?
3719 [main] DEBUG org.hibernate.persister.entity.AbstractEntityPersister  - Upda
te-generated property select: select pet_.MODIFIED_DATE as MODIFIED9_1_ from PET
 pet_ where pet_.ID=?
3750 [main] DEBUG org.hibernate.persister.collection.AbstractCollectionPersister
  - Static SQL for collection: com.menagerie.domain.entity.Owner.pets
3750 [main] DEBUG org.hibernate.persister.collection.AbstractCollectionPersister
  -  Row insert: update PET set OWNER_ID=? where ID=?
3750 [main] DEBUG org.hibernate.persister.collection.AbstractCollectionPersister
  -  Row delete: update PET set OWNER_ID=null where OWNER_ID=? and ID=?
3750 [main] DEBUG org.hibernate.persister.collection.AbstractCollectionPersister
  -  One-shot delete: update PET set OWNER_ID=null where OWNER_ID=?
  • As can be seen, the generated update and insert statements will set data in all the columns irrespective of their being set/changed by the application during the create/modify process. 
  • During the modify the old values will be updated again in the database. Hibernate does this so that it can avoid creating SQL statements on the fly for each such operation thereby improving the application performance. 
  • However in certain cases this is not preferable, e.g.: if the start up time is a bigger concern than the application run-time. Or the table has hundreds of columns. 
In such cases, we can override the default Hibernate behavior to enable queries to be created at run-time. This is achieved by setting the dynamic-insert and dynamic-update attributes to true. This will ensure that null values are not inserted in the table during record creation (dynamic-insert ="true") and unchanged values are not included in record updates (dynamic-update = "true")
Pet /Owner Mapping file changes made:
<class name="com.menagerie.domain.entity.Owner" table="OWNER" dynamic-insert ="true"
    dynamic-update="true">
<class/>

<class name="com.menagerie.domain.entity.Pet" table="PET" dynamic-insert ="true"
    dynamic-update="true">
</class>
To improve the performance further you can set the class as immutable, if it is not updated via code. The change to be made in mapping file is:
<class name="com.menagerie.domain.entity.Owner" table="OWNER" mutable ="false">
<class/>
For models representing master data, this is a good option. Hibernate can apply optimizations such as no static SQL generation, no dirty checking etc.

2 comments:

  1. Thanks for nice article! We will learn more things from you .Keep writing... :)

    ReplyDelete