JPA/Hibernate Tips

  • Best Practices
    • Declare identifier properties on persistent classes with NO business meaning
    • Identify natural/business key – equals/hashcode
    • Do not treat exceptions as recoverable – rollback the transaction and close the connection
    • Prefer lazy fetching for associations
    • Prefer bidirectional associations
    • Use bind variables (NO string manipulations)
    • Using second-level caching for those entity classes that represent
      • Data that changes rarely
      • Noncritical data (eg. Content-management data)
      • Data that’s local to the application and not modified by other applications

  • Inheritance Mapping and Polymorphic Queries
    • SINGLE_TABLE – If you require the best performance and need to use polymorphic queries and relationships, you should choose the single table strategy. But be aware, that you can’t use not null constraints on subclass attributes which increase the risk of data inconsistencies.
    • JOINED – If data consistency is more important than performance and you need polymorphic queries and relationships, the joined strategy is probably your best option.
    • TABLE_PER_CLASS – If you don’t need polymorphic queries or relationships, the table per class strategy is most likely the best fit. It allows you to use constraints to ensure data consistency and provides an option of polymorphic queries. But keep in mind, that polymorphic queries are very complex for this table structure and that you should avoid them.
  • N+1 problems
    • Problem : EAGER fetch type on Many-to-One single point association will generate N+1 small SELECT statements
    • Solution : 1 Huge SELECT statement by the following two changes
      • Change the fetch strategy of single point associations from EAGER to LAZY
      • Write the query based on the requirements (left join fetch) to load the child objects eagerly
    • Batch Fetching : Optimisation of Lazy Fetching Strategy
  • Cascading
    • PERSIST
    • MERGE
  • Locking
    • OptimisticLockingException/Versioning
    • LockModeType.PESSIMITIC_READ/WRITE
  • Isolation rules (on DB) : performance vs. Integrity
    • select @@tx_isolation
    • set global transaction isolation level SERIALIZABLE;
    • hibernate.connection.isolation = 1/2/3/4
    • Levels
      • Serializable
      • Repeatable Read (default MYSQL) : Phantom Reads are available (new inserts will be available)
      • Read Commited (default Oracle) : Unrepeatable Reads are available (updates will be available once commited)
      • Read Uncommited : Dirty Reads are available
  • First-Level Cache
    • Avoid unnecessary DB hits
    • ID based -> maintain only one object
    • Work as Repeatable Read -> good isolation
  • Second-Level Cache
    • No Object is created, key-value based dehydrated data
    • Regions
      • Entity Data Cache (@Cacheable from javax.persistence)
      • Collection Cache (@Cache from hibernate)
      • Query Result Cache
    • Implementations
      • EhCache (single JVM) – EhCacheRegionFactory
      • TreeCache from JBoss
    • javax.persistence.sharedCache.mode
      • ALL
      • ENABLE_SELECTIVE + @Cacheable
    • When entities cached in the second-level cache are updated, Hibernate invalidates them. Or one can invalidate them manually by emf.evict()
    • Concurrency Strategy (@Cache from hibernate with “usage” param)
      • READ ONLY
      • NONSTRICT READ WRITE
      • READ WRITE
      • TRANSACTIONAL
    • Statistic API – entity.*

Leave a Reply