Monday, November 25, 2013

Hibernate cache levels tutorial

One of the common problems of people that start using Hibernate is performance, if you don’t have much experience in Hibernate you will find how quickly your application becomes slow. If you enable sql traces, you would see how many queries are sent to database that can be avoided with little Hibernate knowledge. In current post I am going to explain how to use Hibernate Query Cache to avoid amount of traffic between your application and database.
Hibernate offers two caching levels:
  • The first level cache is the session cache. Objects are cached within the current session and they are only alive until the session is closed.
  • The second level cache exists as long as the session factory is alive. Keep in mind that in case of Hibernate, second level cache is not a tree of objects; object instances are not cached, instead it stores attribute values.
After this brief introduction (so brief I know) about Hibernate cache, let’s see what is Query Cache and how is interrelated with second level cache.
Query Cache is responsible for caching the combination of query and values provided as parameters as key, and list of identifiers of objects returned by query execution as values. Note that using Query Cache requires a second level cache too because when query result is get from cache (that is a list of identifiers), Hibernate will load objects using cached identifiers from second level.
To sum up, and as a conceptual schema, given next query: “from Country where population > :number“, after first execution, Hibernatecaches would contain next fictional values (note that number parameter is set to 1000):
L2 Cache
[
id:1, {name='Spain', population=1000, ....}
id:2, {name='Germany', population=2000,...}
....
]
QueryCache
[{from Country where population > :number, 1000}, {id:2}]
So before start using Query Cache, we need to configure cache of second level.
First of all you must decide what cache provider you are going to use. For this example Ehcache is chosen, but refer to Hibernatedocumentation for complete list of all supported providers.
To configure second level cache, set next Hibernate properties:
hibernate.cache.provider_class = org.hibernate.cache.EhCacheProvider
hibernate.cache.use_structured_entries = true
hibernate.cache.use_second_level_cache = true
And if you are using annotation approach, annotate cachable entities with:
@Cacheable
@Cache(usage = CacheConcurrencyStrategy.NONSTRICT_READ_WRITE)
See that in this case cache concurrency strategy is NONSTRICT_READ_WRITE, but depending on cache provider, other strategies can be followed like TRANSACTIONAL, READ_ONLY, … take a look at cache section of Hibernate documentation to chose the one that fits better with your requirements.
And finally add Ehcache dependencies:

net.sf.ehcache
ehcache-core
2.5.0


org.hibernate
hibernate-ehcache
3.6.0.Final
Now second level cache is configured, but not query cache; anyway we are not far from our goal.
Set hibernate.cache.use_query_cache property to true.
And for each cachable query, we must call setCachable method during query creation:
List list = session.createQuery(“from Country where population > 1000″).setCacheable(true).list();
To make example more practical I have uploaded a full query cache example with Spring Framework. To see clearly that query cacheworks I have used one public database hosted in ensembl.org. The Ensembl project produces genome databases for vertebrates and other eukaryotic species, and makes this information freely available online. In this example query to dna table is cached.
First of all Hibernate configuration:
01@Configuration
02public class HibernateConfiguration {
03 
04 @Value("#{dataSource}")
05 private DataSource dataSource;
06 
07 @Bean
08 public AnnotationSessionFactoryBean sessionFactoryBean() {
09  Properties props = new Properties();
10  props.put("hibernate.dialect", EnhancedMySQL5HibernateDialect.class.getName());
11  props.put("hibernate.format_sql""true");
12  props.put("hibernate.show_sql""true");
13  props.put("hibernate.cache.provider_class""org.hibernate.cache.EhCacheProvider");
14  props.put("hibernate.cache.use_structured_entries""true");
15  props.put("hibernate.cache.use_query_cache""true");
16  props.put("hibernate.cache.use_second_level_cache""true");
17  props.put("hibernate.hbm2ddl.auto""validate");
18 
19  AnnotationSessionFactoryBean bean = new AnnotationSessionFactoryBean();
20  bean.setAnnotatedClasses(new Class[]{Dna.class}); 
21  bean.setHibernateProperties(props);
22  bean.setDataSource(this.dataSource);
23  bean.setSchemaUpdate(true);
24  return bean;
25 }
26 
27}
It is a simple Hibernate configuration, using properties previously explained to configure second level cache.
Entity class is an entity that represents a sequence of DNA.
01@Entity(name="dna")
02@Cacheable
03@Cache(usage = CacheConcurrencyStrategy.NONSTRICT_READ_WRITE)
04public class Dna {
05 
06 @Id
07 private int seq_region_id;
08 
09 private String sequence;
10 
11 public int getSeq_region_id() {
12  return seq_region_id;
13 }
14 
15 public void setSeq_region_id(int seq_region_id) {
16  this.seq_region_id = seq_region_id;
17 }
18 
19 @Column
20 public String getSequence() {
21  return sequence;
22 }
23 
24 public void setSequence(String sequence) {
25  this.sequence = sequence;
26 }
27 
28}
To try query cache, we are going to implement one test where same query is executed multiple times.
01@Autowired
02private SessionFactory sessionFactory;
03 
04@Test
05public void fiftyFirstDnaSequenceShouldBeReturnedAndCached() throws Exception {
06 for (int i = 0; i < 5; i++) {
07  Session session = sessionFactory.openSession();
08  session.beginTransaction();
09 
10  Time elapsedTime = new Time("findDna"+i);
11 
12  List list = session.createQuery(
13    "from dna").setFirstResult(0).setMaxResults(50).setCacheable(true).list();
14 
15 
16  session.getTransaction().commit();
17  session.close();
18  elapsedTime.miliseconds(System.out);
19 
20  for (Dna dna : list) {
21   System.out.println(dna);
22  }
23 
24 }
25}
We can see that we are returning first fifty dna sequences, and if you execute it, you will see that elapsed time between creation of query and commiting transaction is printed. As you can suppose only first iteration takes about 5 seconds to get all data, but the other ones only milliseconds.
The foreach line just before query iteration will print object identifier through console. If you look carefully none of these identifiers will be repeated during all execution. This fact just goes to show you that Hibernate cache does not save objects but properties values, and the object itself is created each time.
Last note, remember that Hibernate does not cache associations by default.
Now after writing a query, think if it will contain static data and if it will be executed often. If it is the case, query cache is your friend to make Hibernate applications run faster.
Reference: Hibernate cache levels tutorial from our JCG partner Alex Soto at the One Jar To Rule Them All blog.

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...

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