Wednesday, March 19, 2014
When should we use intern method of String on String constants
According to String#intern(),
String s = "Example";
String s1 = new String("Example"); // will create new object
String s2 = new String("Example").intern(); // this will create new object
// but as we are calling intern we will get reference of pooled string "Example
intern
method is supposed to return the String from the String pool if the
String is found in String pool, otherwise a new string object will be
added in String pool and the reference of this String is returned.String s = "Example";
String s1 = new String("Example"); // will create new object
String s2 = new String("Example").intern(); // this will create new object
// but as we are calling intern we will get reference of pooled string "Example
Hibernate EhCache configuration tutorial
Caching is facility provided by ORM frameworks which help users to
get fast running web application, while help framework itself to reduce
number of queries made to database in a single transaction. Hibernate also provide this caching functionality, in two layers.
Hibernate ships with the ehcache library. If you want any particular version of ehcache, visit the Terracotta Ehcache download site:
http://www.terracotta.org/products/enterprise-ehcache
The maven dependency is for Ehcache 2.0 and any upgrades is:
Hibernate 3.2 and below
1) If you are using hbm.xml files then use below configuration:
2) Otherwise, if you are using annotations, use these annotations:
For both options, caching strategy can be of following types:
and where queries are defined in your code, add the method call setCacheable(true) to the queries that should be cached:
By
default, Ehcache will create separate cache regions for each entity
that you configure for caching. You can change the defaults for these
regions by adding the configuration to your ehcache.xml. To provide this
configuration file, use this property in hibernate configuration:
And use below configuration to override the default configuration:
Please note that in ehcache.xml, if eternal=”true” then we should not write timeToIdealSeconds, timeToLiveSeconds, hibernate will take care about those values
So if you want to give values manually better use eternal=”false” always, so that we can assign values into timeToIdealSeconds, timeToLiveSeconds manually.
timeToIdealSeconds=”seconds” means, if the object in the global cache is ideal, means not using by any other class or object then it will be waited for some time we specified and deleted from the global cache if time is exceeds more than timeToIdealSeconds value.
timeToLiveSeconds=”seconds” means, the other Session or class using this object or not, i mean may be it is using by other sessions or may not, what ever the situation might be, once it competed the time specified timeToLiveSeconds, then it will be removed from the global cache by hibernate.
- Fist level cache: This is enabled by default and works in session scope. Read more about hibernate first level cache.
- Second level cache: This is apart from first level cache which is available to be used globally in session factory scope.
Sections in this post: How second level cache works About EhCache Configuring EhCache Configuring entity objects Query caching Example application Sourcecode download
How second level cache works
Lets write all the facts point by point:- Whenever hibernate session try to load an entity, the very first place it look for cached copy of entity in first level cache (associated with particular hibernate session).
- If cached copy of entity is present in first level cache, it is returned as result of load method.
- If there is no cached entity in first level cache, then second level cache is looked up for cached entity.
- If second level cache has cached entity, it is returned as result of load method. But, before returning the entity, it is stored in first level cache also so that next invocation to load method for entity will return the entity from first level cache itself, and there will not be need to go to second level cache again.
- If entity is not found in first level cache and second level cache also, then database query is executed and entity is stored in both cache levels, before returning as response of load() method.
- Second level cache validate itself for modified entities, if modification has been done through hibernate session APIs.
- If some user or process make changes directly in database, the there is no way that second level cache update itself until “timeToLiveSeconds” duration has passed for that cache region. In this case, it is good idea to invalidate whole cache and let hibernate build its cache once again. You can use below code snippet to invalidate whole hibernate second level cache.
About EhCache
Terracotta Ehcache is a popular open source Java cache that can be used as a Hibernate second level cache. It can be used as a standalone second level cache, or can be configured for clustering to provide a replicated coherent second level cache.Hibernate ships with the ehcache library. If you want any particular version of ehcache, visit the Terracotta Ehcache download site:
http://www.terracotta.org/products/enterprise-ehcache
The maven dependency is for Ehcache 2.0 and any upgrades is:
1
2
3
4
5
6
| < dependency > < groupId >net.sf.ehcache</ groupId > < artifactId >ehcache</ artifactId > < version >[2.0.0]</ version > < type >pom</ type > </ dependency > |
Configuring EhCache
To configure ehcache, you need to do two steps:- configure Hibernate for second level caching
- specify the second level cache provider
1
2
| < property key = "hibernate.cache.use_second_level_cache" >true</ property > < property name = "hibernate.cache.region.factory_class" >net.sf.ehcache.hibernate.EhCacheRegionFactory</ property > |
1
2
| < property key = "hibernate.cache.use_second_level_cache" >true</ property > < property name = "hibernate.cache.region.provider_class" >net.sf.ehcache.hibernate.EhCacheProvider</ property > |
Configuring entity objects
This may done in two ways.1) If you are using hbm.xml files then use below configuration:
1
2
3
| < class name = "com.application.entity.DepartmentEntity" table = "..." > < cache usage = "read-write" /> </ class > |
1
2
3
4
5
6
7
| @Entity @Cache (usage=CacheConcurrencyStrategy.READ_ONLY, region= "department" ) public class DepartmentEntity implements Serializable { //code } |
- none : No caching will happen.
- read-only : If your application needs to read, but not modify, instances of a persistent class, a read-only cache can be used.
- read-write : If the application needs to update data, a read-write cache might be appropriate.
- nonstrict-read-write : If the application only occasionally needs to update data (i.e. if it is extremely unlikely that two transactions would try to update the same item simultaneously), and strict transaction isolation is not required, a nonstrict-read-write cache might be appropriate.
- transactional : The transactional cache strategy provides support for fully transactional cache providers such as JBoss TreeCache. Such a cache can only be used in a JTA environment and you must specify hibernate.transaction.manager_lookup_class.
Query caching
You can also enable query caching. To do so configure it in your hbm.xml:
1
| < property key = "hibernate.cache.use_query_cache" >true</ property > |
1
| sessionFactory.getCurrentSession().createQuery( "..." ).setCacheable( true ).list(); |
1
| < property name = "net.sf.ehcache.configurationResourceName" >/ehcache.xml</ property > |
1
2
3
4
5
6
7
8
| < cache name = "com.somecompany.someproject.domain.Country" maxElementsInMemory = "10000" eternal = "false" timeToIdleSeconds = "300" timeToLiveSeconds = "600" overflowToDisk = "true" /> |
So if you want to give values manually better use eternal=”false” always, so that we can assign values into timeToIdealSeconds, timeToLiveSeconds manually.
timeToIdealSeconds=”seconds” means, if the object in the global cache is ideal, means not using by any other class or object then it will be waited for some time we specified and deleted from the global cache if time is exceeds more than timeToIdealSeconds value.
timeToLiveSeconds=”seconds” means, the other Session or class using this object or not, i mean may be it is using by other sessions or may not, what ever the situation might be, once it competed the time specified timeToLiveSeconds, then it will be removed from the global cache by hibernate.
Hibernate second level cache
The second level cache is used across sessions,
which also differentiates it from the session cache, which only – as the
name says – has session scope. Hibernate provides a flexible concept to
exchange cache providers for the second-level cache. By default
Hibernate uses Ehcache as caching provider, however JBoss AS 6 and 7 use
Infinispan as caching provider.
One difference with the first level cache is that it's not on by default but it needs some configuration in your persistence.xml to tell Hibernate to turn on the cache. The configuration differs depending on the version of JBoss AS used. Let's see each configuration in detail.
JBoss AS 5 uses JBoss Cache as caching provider. This is the configuration required to turn on the 2nd level cache on JBoss 5:
By setting the property hibernate.cache.use_second_level_cache to true we are turning on the second-level cache mechanism. The cache, by default, is activated only for entities, so we also need to explicitly set hibernate.cache.use_query_cache to true if we want to cache queries as well.
The second-level cache can be implemented using several different schemas—open source and commercial. In the next property, hibernate.cache.region.factory_class, we are telling Hibernate to use JBoss Cache as the second-level cache implementation.
The next parameter, hibernate.cache.region.jbc2.cachefactory, is specific to the JBoss Cache implementation. It specifies the JNDI name under which the CacheManager to be used is bound. There is no default value, thus the user must specify the property.
The hibernate.cache.region.jbc2.cfg.collection property is also specific to JBoss Cache and details the name of the configuration that should be used for collection caches (in our configuration, mvcc-entity).
JBoss AS 6 uses Infinispan 4 as cache provider. The required properties for persistence.xml follows here:
The relevant part of this configuration is the cache manager which is bound in the JNDI tree under the name java:CacheManager/entity
The JNDI name to which the hibernate cache container is bound is defined in infinispan-configs.xml:
JBoss AS 7 uses Infinispan 5 as caching provider. Here's the suggested configuration:
In JBoss 7 the Infinispan cache manager is bound under the java:jboss/infinispan/hibernate name and is configured into the standalone-ha.xml or domain.xml inside the infinispan subsystem:
One difference with the first level cache is that it's not on by default but it needs some configuration in your persistence.xml to tell Hibernate to turn on the cache. The configuration differs depending on the version of JBoss AS used. Let's see each configuration in detail.
Using second level cache with JBoss AS 5
JBoss AS 5 uses JBoss Cache as caching provider. This is the configuration required to turn on the 2nd level cache on JBoss 5:
01.
<
properties
>
02.
03.
<
property
name
=
"hibernate.cache.use_second_level_cache"
value
=
"true"
/>
04.
<
property
name
=
"hibernate.cache.use_query_cache"
value
=
"true"
/>
05.
06.
<
property
name
=
"hibernate.cache.region.factory_class"
value
=
"org.hibernate.cache.jbc2.JndiMultiplexedJBossCacheRegionFactory"
/>
07.
<
property
name
=
"hibernate.cache.region.jbc2.cachefactory"
value
=
"java:CacheManager"
/>
08.
<
property
name
=
"hibernate.cache.region.jbc2.cfg.entity"
value
=
"mvcc-entity"
/>
09.
<
property
name
=
"hibernate.cache.region.jbc2.cfg.collection"
value
=
"mvcc-entity"
/>
10.
</
properties
>
By setting the property hibernate.cache.use_second_level_cache to true we are turning on the second-level cache mechanism. The cache, by default, is activated only for entities, so we also need to explicitly set hibernate.cache.use_query_cache to true if we want to cache queries as well.
The second-level cache can be implemented using several different schemas—open source and commercial. In the next property, hibernate.cache.region.factory_class, we are telling Hibernate to use JBoss Cache as the second-level cache implementation.
The next parameter, hibernate.cache.region.jbc2.cachefactory, is specific to the JBoss Cache implementation. It specifies the JNDI name under which the CacheManager to be used is bound. There is no default value, thus the user must specify the property.
The hibernate.cache.region.jbc2.cfg.collection property is also specific to JBoss Cache and details the name of the configuration that should be used for collection caches (in our configuration, mvcc-entity).
Using second level cache with JBoss AS 6
JBoss AS 6 uses Infinispan 4 as cache provider. The required properties for persistence.xml follows here:
1.
<
properties
>
2.
<
property
name
=
"hibernate.cache.use_second_level_cache"
>true</
property
>
3.
<
property
name
=
"hibernate.cache.use_query_cache"
>true</
property
>
4.
<
property
name
=
"hibernate.cache.region.factory_class"
>org.hibernate.cache.infinispan.JndiInfinispanRegionFactory</
property
>
5.
<
property
name
=
"hibernate.cache.infinispan.cachemanager"
>java:CacheManager/entity</
property
>
6.
</
properties
>
The relevant part of this configuration is the cache manager which is bound in the JNDI tree under the name java:CacheManager/entity
The JNDI name to which the hibernate cache container is bound is defined in infinispan-configs.xml:
1.
<
infinispan-config
name
=
"hibernate"
jndi-name
=
"java:CacheManager/entity"
>
2.
<
infinispan-config
xmlns
=
"urn:infinispan:config:4.2"
>
3.
...
4.
</
infinispan-config
>
5.
</
persistence
>
Using second level cache with JBoss AS 7
JBoss AS 7 uses Infinispan 5 as caching provider. Here's the suggested configuration:
1.
<
shared-cache-mode
>ENABLE_SELECTIVE</
shared-cache-mode
>
2.
<
properties
>
3.
<
property
name
=
"hibernate.cache.use_second_level_cache"
value
=
"true"
/>
4.
<
property
name
=
"hibernate.cache.use_query_cache"
value
=
"true"
/>
5.
<
property
name
=
"hibernate.cache.infinispan.cachemanager"
value
=
"java:jboss/infinispan/hibernate"
/>
6.
<
property
name
=
"hibernate.cache.region.factory_class"
value
=
"org.hibernate.cache.infinispan.JndiInfinispanRegionFactory"
/>
7.
</
properties
>
In JBoss 7 the Infinispan cache manager is bound under the java:jboss/infinispan/hibernate name and is configured into the standalone-ha.xml or domain.xml inside the infinispan subsystem:
01.
<
subsystem
xmlns
=
"urn:jboss:domain:infinispan:1.0"
default-cache-container
=
"cluster"
>
02.
. . . . . .
03.
<
cache-container
name
=
"hibernate"
default-cache
=
"local-query"
>
04.
<
invalidation-cache
mode
=
"SYNC"
name
=
"entity"
>
05.
<
locking
isolation
=
"REPEATABLE_READ"
/>
06.
<
eviction
strategy
=
"LRU"
max-entries
=
"10000"
/>
07.
<
expiration
max-idle
=
"100000"
/>
08.
</
invalidation-cache
>
09.
<
local-cache
name
=
"local-query"
>
10.
<
eviction
strategy
=
"LRU"
max-entries
=
"10000"
/>
11.
<
expiration
max-idle
=
"100000"
/>
12.
</
local-cache
>
13.
<
replicated-cache
mode
=
"ASYNC"
name
=
"timestamps"
>
14.
<
eviction
strategy
=
"NONE"
/>
15.
</
replicated-cache
>
16.
</
cache-container
>
17.
</
subsystem
>
Disadvantages of Hibernate
• Debugging- Sometimes debugging and performance tuning becomes difficult.
• Slower than JDBC- Hibernate is slower than pure JDBC as it is generating lots of SQL statements in runtime.
• Not suitable for Batch processing- It advisable to use pure JDBC for batch processing.
• Overhead-Use of Hibernate is an overhead for the applications which are : simple and use one database that never change, need to put data to database tables, no further SQL queries and there are no objects which are mapped to two different tables. Hibernate increases extra layers and complexity. So for these types of applications JDBC is the best choice.
• Difficult to maintain- Anybody wanting to maintain application using Hibernate will need to know Hibernate.
• Performance decreases in complex data-For complex data, mapping from Object-to-tables and vice versa reduces performance and increases time of conversion.
• Not allow all queries- Hibernate does not allow some type of queries which are supported by JDBC. For example it does not allow inserting multiple objects to same table using single query. Developer has to write separate query to insert each object.
• High memory consumption- Loading a large number of objects from the database which then reside in memory cause to waste the memory. One approach to resolving this is by using lazy loading, which has a few of its own caveats.
• Difficulties in legacy databases- Hibernate works best and easiest with a brand new database, attempting to use it on an existing legacy database can be quite a difficult task.
• Learning difficulties – In here you may mess with advantages. Note that it is quite easy to do the basics in hibernate but to really use hibernate well you need a good knowledge of ORM concepts, the way mappings and the session works and also more advanced concepts such as caching, lazy loading and fetching strategies.
• Performance optimization -Trying to optimize performance at the database level is a bit trickier with Hibernate due to the fact the SQL that is executed is actually generated by Hibernate, hence user not able to just go in and adjust the SQL accordingly.
• Slower than JDBC- Hibernate is slower than pure JDBC as it is generating lots of SQL statements in runtime.
• Not suitable for Batch processing- It advisable to use pure JDBC for batch processing.
• Overhead-Use of Hibernate is an overhead for the applications which are : simple and use one database that never change, need to put data to database tables, no further SQL queries and there are no objects which are mapped to two different tables. Hibernate increases extra layers and complexity. So for these types of applications JDBC is the best choice.
• Difficult to maintain- Anybody wanting to maintain application using Hibernate will need to know Hibernate.
• Performance decreases in complex data-For complex data, mapping from Object-to-tables and vice versa reduces performance and increases time of conversion.
• Not allow all queries- Hibernate does not allow some type of queries which are supported by JDBC. For example it does not allow inserting multiple objects to same table using single query. Developer has to write separate query to insert each object.
• High memory consumption- Loading a large number of objects from the database which then reside in memory cause to waste the memory. One approach to resolving this is by using lazy loading, which has a few of its own caveats.
• Difficulties in legacy databases- Hibernate works best and easiest with a brand new database, attempting to use it on an existing legacy database can be quite a difficult task.
• Learning difficulties – In here you may mess with advantages. Note that it is quite easy to do the basics in hibernate but to really use hibernate well you need a good knowledge of ORM concepts, the way mappings and the session works and also more advanced concepts such as caching, lazy loading and fetching strategies.
• Performance optimization -Trying to optimize performance at the database level is a bit trickier with Hibernate due to the fact the SQL that is executed is actually generated by Hibernate, hence user not able to just go in and adjust the SQL accordingly.
Subscribe to:
Posts (Atom)