martes, enero 31, 2012

Giuro per sempre a te, Di viver, morire per te, Se tu sarai con me lo so, Dea Roma, vincerò!



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, Hibernate caches 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 Hibernate documentation 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:

<dependency>
<groupId>net.sf.ehcache</groupId>
<artifactId>ehcache-core</artifactId>
<version>2.5.0</version>
</dependency>
<dependency>
<groupId>org.hibernate</groupId>
<artifactId>hibernate-ehcache</artifactId>
<version>3.6.0.Final</version>
</dependency>

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<Country> 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 cache works 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:


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.

To try query cache, we are going to implement one test where same query is executed multiple times.


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.


Download Code

Music: http://www.youtube.com/watch?v=fw1VJSU92mw

6 comentarios:

louis gueye dijo...

I there,

Very nice article. It explains the "why" and the "how" in a methodical fashion.

Thank you really, your article just became my "reference post" for setting up Hibernate second level cache.

Louis.

Anónimo dijo...

you can use session factory statistics to show the number of cache hits and other useful information

Ramon Bastos dijo...
Este comentario ha sido eliminado por un administrador del blog.
Alex Soto dijo...

Hi Louis, thank you very much for reading my blog, it makes me feel so happy when one of my post makes developers' life easier.

I know that I could use sessionfactory statistics, in fact I thought to show that information too, but finally I chose to only show time.

Keep reading,
Alex.

chenlina dijo...

chenlina20160716
beats solo
louis vuitton outlet
christian louboutin outlet
mont blanc fountain pens
gucci handbags
coach factory outlet
cheap jordans
true religion outlet
supra sneakers
fitflops shoes
lebron james shoes 13
nike air max 90
polo ralph lauren outlet
louis vuitton handbags
cheap oakley sunglasses
nike blazers
true religion outlet
michael kors outlet
coach canada
michael kors outlet clearance
burberry outlet
michael kors outlet
louis vuitton purses
toms outlet
celine handbags
michael kors handbags
louis vuitton outlet stores
coach outlet
coach outlet
ghd hair straighteners
louis vuitton outlet
adidas nmd
toms shoes
true religion outlet
ray ban sunglasses discount
oakley sunglasses
louis vuitton bags
michael kors outlet
louis vuitton
hermes handbags
as

Gege Dai dijo...

football shirts
cheap oakley sunglasses
gucci outlet online
michael kors outlet
swarovski outlet
michael kors outlet
michael kors outlet
nike outlet store
tiffany and co
celine outlet online
nhl jerseys
true religion outlet
ralph lauren polo
true religion jeans
toms outlet
michael kors handbags outlet
michael kors outlet
hermes birkin bag
rolex orologi
juicy couture outlet
tory burch sandals
fitflops sale
polo ralph lauren
michael kors outlet
herve leger dresses
nike trainers
valentino outlet
lebron james shoes
hollister uk
ray ban sunglasses
fitflops sale
michael kors outlet
fitflops shoes
coach outlet
louis vuitton sunglasses for women
czq20160722

Donate If You Can and Find Post Useful