Java Goodness – Top 5 Must know about JPA/Hibernate for Interviews

When appearing for Java interviews, you got to be strong in your DB, here are some of the basics you must know
  • Difference between Hibernate and JPA

JPA is J2EE5 specification on how the ORM layer should be implemented, so essentially its an Interface, But Hibernate-JPA is a concrete Implementation of JPA , I mentioned Hibernate-JPA as there is Hibernate-Hibernate which has been there before JPA, and JPA has been heavily inspired from it.
Also, JPQL (Query lang of JPA) query is always a Valid HQL query
  • JPA Performance Optimization

As Java Developers, we only like to work with Objects, whereas RDBMS is more table oriented, Resolving this difference is called “Object/relational imependance” and can result in substantial overhead, which inturn can materialize in poor application performance.
JPA ORM is the bridge between the two, you need to know the Inner workings of JPA like
  1. What are the actual queries performed against a RDBMS (In Spring MVC, turn it on by show_sql=true in XML Config)
  2. How long does it take
  3. Are we effectively using Cache or is it hitting the database each time

How long does it take
This can be measured by adding a simple Aspect of StopWatch, here is an example
package com.webforefront.aop;
import org.apache.commons.lang.time.StopWatch;
import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
import org.aspectj.lang.ProceedingJoinPoint;
import org.aspectj.lang.annotation.Around;
import org.aspectj.lang.annotation.Pointcut;
import org.aspectj.lang.annotation.Aspect;
@Aspect
public class DAOInterceptor {
private Log log = LogFactory.getLog(DAOInterceptor.class);
@Around("execution(* com.webforefront.jpa.service..*.*(..))")
public Object logQueryTimes(ProceedingJoinPoint pjp) throws Throwable {
StopWatch stopWatch = new StopWatch();
stopWatch.start();
Object retVal = pjp.proceed();
stopWatch.stop();
String str = pjp.getTarget().toString();
log.info(str.substring(str.lastIndexOf(".")+1, str.lastIndexOf("@")) + " - " + pjp.getSignature().getName() + ": " + stopWatch.getTime() + "ms");
return retVal;
}
}
view rawJPA-Timer hosted with ❤ by GitHub
Get the Database statistics Similar to obtaining the timing for the queries,we can retrieve the Hibernate Statistics, for ReadCount , hits etc,
package com.webforefront.aop;
import org.hibernate.stat.Statistics;
import org.hibernate.SessionFactory;
import org.aspectj.lang.ProceedingJoinPoint;
import org.aspectj.lang.annotation.Around;
import org.aspectj.lang.annotation.Aspect;
import org.springframework.beans.factory.annotation.Autowired;
import javax.persistence.EntityManagerFactory;
import org.hibernate.ejb.HibernateEntityManagerFactory;
import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
@Aspect
public class CacheHibernateInterceptor {
private Log log = LogFactory.getLog(DAOInterceptor.class);
@Autowired
private EntityManagerFactory entityManagerFactory;
@Around("execution(* com.webforefront.jpa.service..*.*(..))")
public Object log(ProceedingJoinPoint pjp) throws Throwable {
HibernateEntityManagerFactory hbmanagerfactory = (HibernateEntityManagerFactory) entityManagerFactory;
SessionFactory sessionFactory = hbmanagerfactory.getSessionFactory();
Statistics statistics = sessionFactory.getStatistics();
String str = pjp.getTarget().toString();
statistics.setStatisticsEnabled(true);
log.info(str.substring(str.lastIndexOf(".")+1, str.lastIndexOf("@")) + " - " + pjp.getSignature().getName() + ": (Before call) " + statistics);
Object result = pjp.proceed();
log.info(str.substring(str.lastIndexOf(".")+1, str.lastIndexOf("@")) + " - " + pjp.getSignature().getName() + ": (After call) " + statistics);
return result;
}
}
view rawHibernate-Statistics hosted with ❤ by GitHub


Possible Solutions

Once you are armed with these answers, you can effectively improve performance by

    • Optimize Lazy and Eager Loading
    • Caching Mechanisms – Using Second Level Cache Like EhCache
    • Iterating through Relations Efficiently – Load In Batches




  • First and Second Level Caching

There are 2 cache levels in Hibernate:
  • 1st level or the session cache.
  • 2nd level or the SessionFactory level Cache.
The 1st level cache is mandatory and is taken care by Hibernate.
This 2nd level cache can be implemented via various 3rd party cache implementations. EhCache is the default one, there are several other possibilities like : SwarmCache and OSCache.
‘second-level’ cache exists as long as the session factory is alive. It holds on to the ‘data’ for all properties and associations (and collections if requested) for individual entities that are marked to be cached.
Below is the list of Cache Strategies which need to defined for each entity for Second Level Cache
  1. Read Only – If your application needs to read, but not modify, instances of a persistent class, a read-only cache can be used.
  2. Nonrestrick read/write -
    • Caches data that is sometimes updated without ever locking the cache.
    • If concurrent access to an item is possible, this concurrency strategy makes no guarantee that the item returned from the cache is the latest version available in the database. Configure your cache timeout accordingly! This is an “asynchronous” concurrency strategy.

  3. Strategy: read/write(usage=”read-write”)
    • If the application needs to update data, a read-write cache might be appropriate.
  4. Strategy: transactional
    • Support fully transactional cache implementations like JBoss TreeCache.

  • One to Many and Many to Many Relationships

  • Criteria Queries

This is new in JPA 2.0, Although JPQL is very flexible, it has some problems that make working with it more difficult than necessary. For starters, JPQL queries are stored as strings and the compiler has no way of validating JPQL syntax. Additionally, JPQL is not type safe. We could write a JPQL query in which our where clause could have a string value for a numeric property and our code would compile and deploy just fine.
To get around the JPQL limitations described in the previous paragraph, the Criteria API was introduced to JPA in version 2.0 of the specification. The Criteria API allows us to write JPA queries programmatically, without having to rely on JPQL.

Orginally published in Jan 2014

Comments

Popular posts from this blog

Apache Airflow Wait Between Tasks

Hibernate Interview Questions

Java Spring Interview Questions