Tuesday, December 10, 2013

Versioning & Optimistic Locking In Hibernate

By Jim White (Directory of Training and Instructor)
A few weeks ago while teaching Hibernate, a student (thanks Dan) asked me about whether version numbers can be generated by the database.  The answer is – Yes, in some cases.  I thought the question and an expanded discussion of Hibernate’s versioning property would be a good topic for this week’s blog entry.

The Property (Or @Version Annotation)

For those of you that use Hibernate today, you are probably aware that Hibernate can provide optimistic locking through a version property on your persistent objects.  Furthermore, the version property is automatically managed by Hibernate.
To specify a version for your persistent object, simply add a version (or timestamp) property in your mapping file and add a version attribute to your persistent class.  Here is an example on a Product class.
public class Product {
    private long id;
    private String name;
    private String model;
    private double cost;
    private long version;
}

 
         
           
       

        
       
       
       
 
 
For those using annotations, just mark the version property’s getter in the class with the @Version annotation.
@Version public long getVersion() {
    return version;
}
The version property on the class can be numeric (short, int, or long) or timestamp or calendar.  However, another configuration element is provided for timestamps or calendars (covered below).
With automatic versioning (and version set to a numeric), Hibernate will use the version number to check that the row has not been updated since the last time it was retrieved when updating the persistent object (Product in this example).  Notice the extra where “and version = X” clause below, when a product from above is updated.
Hibernate:
    /* update
        com.intertech.domain.Product */ update
            Product
        set
            version=?,
            name=?,
            model=?,
            cost=?
        where
            id=?
            and version=?
If the version has been updated, Hibernate throws a StaleObjectStateException and the transaction (and any persistent object changes) rollback.  If the update commits without issue, Hibernate also increments the version number automatically (note the “set version = ?” as part of the update clause above).

Hibernate Versus The Database Managing The Version

Under this configuration and in this example, Hibernate (from within your Java application) is managing the version number.  However, some DBA’s may prefer to have the version controlled by database rather than Hibernate, especially when the database may be a timestamp and the application is distributed to multiple systems (maybe even timezones).  If the Hibernate application is on different systems that are not time synchronized, the timestamp generated by each system might be different thereby generating improper optimistic lock success or failures.  To inform Hibernate to have the database manage the version, include a generated=”always” attribute in the Hibernate mapping of the persistent object.

 
         
           
       

        generated=”always”
/>
       
       
       
 

Hibernate will now defer to the database to generate the necessary version and update the persistent object’s row accordingly.  A warning is in order however.  This will cause Hibernate to issue an extra SQL to get the version number back from the database after a successful update or insert.  Note the extra SQL issued below after a successful update of a product (Hibernate even comments it to indicate why it is needed).  You might also note that the version number is not set as above when updating the product.  Again, Hibernate is now totally deferring to the database to manage this property.
Of important note, not all dialects (i.e. databases) support the managing of the version number.  HSQLDB, for example, does not allow the version number to be controlled from the database.
Hibernate:
    /* update
        com.intertech.domain.Product */ update
            Product
        set
            name=?,
            model=?,
            cost=?
        where
            id=?
            and version=?
Hibernate:
    /* get generated state com.intertech.domain.Product */ select
        product_.version as version8_
    from
        Product product_
    where
        product_.id=?

Timestamps For Version

In many situations, your DBA or organization may prefer a timestamp to be used as the version indicator.  In theory, the timestamp is a little less safe than a version number.  This is because a timestamp can, in theory, be updated by two transactions at the exact same time (depends on the precision of the database) and allow both to update causing a last in wins scenario (violating the optimistic lock).  It can also be argued that timestamps also take up more space in the database.  Depending on the dialect, the use of a timestamp may incur an additional hit of the database to get the timestamp.  However, on the plus side, timestamps provide useful information about the “when” a row was last altered.  In cases of auditing or record tracking, this might be important information.  Version numbers don’t provide any context for when an update occurred.
If a timestamp is useful, change your version property to be a java.util.Date or Calendar and use a (rather than using a ) element in the mapping file.
public class Product {
    private Date version;
}

 
         
           
       

        <!––>
                
       
       
  
 
The and are equivalent, but it might help the reader to better see/understand that the version is an effectivity timestamp versus a numerical indicator.
You might also notice the source=”db” in the mapping configuration above.  The source attribute can be set to “vm” (for virtual machine) or “db” (for database).  When set to “db”, the database creates and manages the version timestamp (equivalent to generated=”always”) above.  As mentioned above, in the case of the database managing the version timestamp, your application may incur an additional hit of the database as Hibernate must first retrieve the timestamp before updating the row.  Further, as the Hibernate documentation says:  “Not all Dialects are known to support the retrieval of the database’s current timestamp.”

Optimistic Locking Without A Version

Your application may need to deal with a legacy database and the database cannot be altered to contain a version (numeric or timestamp) column.  In this case, Hibernate provides two additional options for optimistic lock management.  You can use all the fields of the persistent object to check that nothing in a row was modified before updating a row.  Set the optimistic-lock=”all” attribute (and dynamic-update=”true”) in the element to use this approach.  The SQL issued by Hibernate will then use each property as a check in the where clause as shown below.
Hibernate:
    /* update
        com.intertech.domain.Product */ update
            Product
        set
            name=?
        where
            id=?
            and name=?
            and model=?
            and cost=?
comparison of the state of all fields in a row but without a version or timestamp property mapping, turn on optimistic-lock="all" in the  mapping
As a slight alternative to this approach, you can set optimistic-lock=”dirty” and then Hibernate will only use modified columns as part of the optimistic check (see below).  This last approach actually allows to transactions to update the same object concurrently legally, but only if they are modifying different columns – something that might be advantageous in a larger application setting where many people are accessing the same objects (thus rows) but rarely updating the same properties (columns).
Hibernate:
    /* update
        com.intertech.domain.Product */ update
            Product
        set
            name=?
        where
            id=?
            and name=?
See the Hibernate documentation for more details on these alternatives to versioning.
Come join us to learn more about Hibernate!  Sign up for Complete Hibernate at Intertech.com here.

5 comments:

oakleyses said...

louis vuitton handbags, oakley sunglasses, louboutin, longchamp outlet, nike shoes, louis vuitton outlet stores, chanel handbags, burberry outlet, prada outlet, jordan shoes, tiffany and co, michael kors outlet, tory burch outlet, louis vuitton outlet, longchamp handbags, nike free, true religion jeans, michael kors outlet, kate spade outlet, polo ralph lauren outlet, tiffany and co, prada handbags, polo ralph lauren outlet, michael kors outlet, michael kors outlet, longchamp handbags, oakley sunglasses, ray ban sunglasses, kate spade handbags, burberry outlet, louis vuitton outlet, louboutin outlet, louboutin, coach factory outlet, air max, air max, coach outlet, gucci outlet, christian louboutin shoes, michael kors outlet, coach purses, ray ban sunglasses, michael kors outlet, louis vuitton, coach outlet store online, true religion jeans, oakley sunglasses cheap

oakleyses said...

ralph lauren, lululemon, air max, hollister, north face, nike air max, polo lacoste, vanessa bruno, timberland, vans pas cher, louboutin, louis vuitton, oakley pas cher, air max pas cher, nike roshe run, air max, true religion outlet, barbour, sac longchamp, air force, hollister, sac louis vuitton, nike free, polo ralph lauren, nike trainers, louis vuitton uk, nike roshe, sac hermes, longchamp, michael kors, sac burberry, sac guess, mulberry, new balance pas cher, converse pas cher, sac louis vuitton, hogan outlet, nike tn, north face, true religion outlet, ray ban pas cher, michael kors, air jordan, nike blazer, nike free pas cher, michael kors pas cher, abercrombie and fitch, ray ban sunglasses

oakleyses said...

mac cosmetics, mont blanc, marc jacobs, canada goose outlet, nike huarache, vans shoes, soccer jerseys, hollister, giuseppe zanotti, beats by dre, abercrombie and fitch, longchamp, insanity workout, celine handbags, bottega veneta, ghd, nfl jerseys, north face outlet, chi flat iron, ugg boots, birkin bag, ugg australia, canada goose, herve leger, ugg pas cher, rolex watches, valentino shoes, canada goose uk, canada goose, ferragamo shoes, canada goose, ugg boots, uggs outlet, north face jackets, soccer shoes, asics running shoes, new balance shoes, p90x, lululemon outlet, canada goose jackets, mcm handbags, instyler, babyliss pro, ugg, wedding dresses, jimmy choo outlet, reebok outlet, nike roshe run

oakleyses said...

parajumpers, karen millen, air max, converse, pandora charms, moncler, louboutin, moncler, links of london, lancel, juicy couture outlet, oakley, hollister, pandora charms, supra shoes, thomas sabo, canada goose, gucci, wedding dresses, timberland boots, swarovski crystal, air max, coach outlet store online, moncler, ray ban, canada goose, moncler, ugg, louis vuitton, swarovski, hollister, montre homme, moncler, hollister clothing store, ralph lauren, rolex watches, moncler outlet, moncler, iphone 6 cases, baseball bats, juicy couture outlet, toms shoes, vans, pandora jewelry, ugg, converse shoes

Anna said...

Great and Useful Article.

Online Java Course

Java Online Training

Java Course Online

Best Recommended books for Spring framework

Java Interview Questions












Java Training Institutes in Chennai

Java Training in Chennai

J2EE Training in Chennai

java j2ee training institutes in chennai

Java Course in Chennai