Hibernate Questions and Answers
Hibernate Questions and Answers
How to call get records in Hibernate using get and load method
If you look at below code , there is not much difference on calling get() and load() method, though
both are overloaded now and can accept few more parameters but the primary methods looks
exactly identical. It’s their behavior which makes them different.
//Example of calling get method of Hiberante Session class
Session session = SessionFactory.getCurrentSession();
Employee Employee = (Employee) session.get(Employee.class, EmployeeID);
<prop key="hibernate.cache.use_second_level_cache">true</prop>
<prop key="hibernate.cache.provider_class">org.hibernate.cache.EhCacheProvider</prop>
Availability
First level cache is available only until the session is open, once the session is closed; the first level
cache is destroyed. On the other hand, second level cache is available through the application's life-
cycle; it is only destroyed and recreated when you restart your application.
Order
If an entity or object is loaded by calling the get() method then Hibernate first checked the first level
cache, if it doesn't found the object then it goes to the second level cache if configured. If the object
is not found then it finally goes to the database and returns the object, if there is no corresponding
row in the table then it return null. When an object is loaded from the database is put on both
second level and first level cache, so that other session who requests the same object can now get it
from the second level cache.
In case if the object is not found in the first level cache but found in the second level cache because
some other sessions have loaded the object before then it is not only returned from first level cache
but also cached at first level cache, so that next time if your code request the same object, it should
be returned from 1st level cache rather than going to the 2nd level cache.
When an object is pass to save(), update(), or saveOrUpdate() method and retrieved by load(), get(),
list(), iterate(), or scroll() method, that object is added to the internal cache of the Session and when
the flush() is subsequently called, the state of the object is synchronized with the database.
Second level cache can also be configured on a per-class and per-collection basis, which means it,
can cache a class or a collection. You can use class-cache and collection-cache elements
in hibernate.cfg.xml to specify which class or collection to cache at 2nd level cache. You should
remember that second level cache by default doesn't cache any entity until you configure it.
You can also use JPA Annotation @Cacheable to specify which entity is cacheable and Hibernate
annoation @Cache to specify caching strategy e.g. CacheConcurrencyStrategies like READ_WRITE or
READ_ONLY to tell Hibernate how the second level cache should behave.
<property name="hibernate.cache.use_query_cache">true</property>
And in code, we need to use setCacheable(true) method of Query, quick example looks like below.
You will not see any select query fired because the load is lazy and it will not load object until you
call any method other than the getId(), Now, if you make the class final and reprint the name of the
class, you will see the actual name of the class as "Customer". You will also see the select queries
fired by hibernate to initialize the object.
You should now understand how costly it can be if you are creating too many objects and only
accessing their getId() method, as it will result in lots of database calls. That's why you should not
make your JPA Entity or Hibernate persistence class final in Java.
Important points to about Entity class, Final, and Proxying
1) Hibernate doesn't create a proxy for final class, instead, they use the real class, but Hibernate
does create a proxy for a non-final class with final methods.
2) Since in Java, you cannot override final methods, the code inside final method remains
unchanged in the proxy class. Which means, if you call a final method on a proxy, it will simply
delegate the call to the super class method? You should be careful not to modify state on final
method because calling them on proxy has a good chance of throwing NullPointerException, as the
object was likely to be not initialized at that point.
In short, avoid final methods on hibernate entity class, until you know what you are doing.
Hibernate reference also stress this point "You should avoid declaring public final methods as this
will again limit the ability to generate proxies from this class. If you want to use a class with public
final methods, you must explicitly disable proxying".
3) As per Hibernate documentation, if you're going to make a class final you should explicitly disable
proxy generation by adding @Proxy(lazy=false), but I haven't noticed any differences between
doing that and just making the class final.
4) You should also disable proxy generation if you're going to make any public methods final in
persistent class, as hibernate will not be able to override them to put its smart code which triggers
lazy loading etc.
5) If you really want to make the Hibernate entity classes final then you can do it by having your
entity implement an interface that declares all of its public methods. This will still allow Hibernate to
use proxies.
In short, making a JPA Entity or Hibernate Persistence class final, limits the ability of Hibernate to
use Proxies, which in turn prevent Hibernate from applying some performance optimizations.
Without proxies, your application loses lazy loading, and lazy association fetching will issue more
SQL queries and make more database roundtrip, which will cost performance.
The only way to make a Hibernate entity class final without losing lazy behavior is to use interface
and define all public methods of persistence class there, this will still allow Hibernate to use a proxy
in place of real class.
import javax.persistence.Access;
import javax.persistence.AccessType;
import javax.persistence.Column;
import javax.persistence.Entity;
import javax.persistence.GeneratedValue;
import javax.persistence.GenerationType;
import javax.persistence.Id;
import javax.persistence.OneToOne;
import javax.persistence.Table;
import org.hibernate.annotations.Cascade;
@Entity
@Table(name = "EMPLOYEE")
@Access(value=AccessType.FIELD)
public class Employee {
@Id
@GeneratedValue(strategy = GenerationType.IDENTITY)
@Column(name = "emp_id")
private long id;
@Column(name = "emp_name")
private String name;
@OneToOne(mappedBy = "employee")
@Cascade(value = org.hibernate.annotations.CascadeType.ALL)
private Address address;
import javax.persistence.Access;
import javax.persistence.AccessType;
import javax.persistence.Column;
import javax.persistence.Entity;
import javax.persistence.GeneratedValue;
import javax.persistence.Id;
import javax.persistence.OneToOne;
import javax.persistence.PrimaryKeyJoinColumn;
import javax.persistence.Table;
import org.hibernate.annotations.GenericGenerator;
import org.hibernate.annotations.Parameter;
@Entity
@Table(name = "ADDRESS")
@Access(value=AccessType.FIELD)
public class Address {
@Id
@Column(name = "emp_id", unique = true, nullable = false)
@GeneratedValue(generator = "gen")
@GenericGenerator(name = "gen", strategy = "foreign", parameters = { @Parameter(name =
"property", value = "employee") })
private long id;
@Column(name = "address_line1")
private String addressLine1;
@OneToOne
@PrimaryKeyJoinColumn
private Employee employee;
<cache name="org.hibernate.cache.internal.StandardQueryCache"
maxEntriesLocalHeap="5" eternal="false" timeToLiveSeconds="120">
<persistence strategy="localTempSwap" />
</cache>
<cache name="org.hibernate.cache.spi.UpdateTimestampsCache"
maxEntriesLocalHeap="5000" eternal="true">
<persistence strategy="localTempSwap" />
</cache>
</ehcache>
Annotate entity beans with @Cache annotation and caching strategy to use. For example,
import org.hibernate.annotations.Cache;
import org.hibernate.annotations.CacheConcurrencyStrategy;
@Entity
@Table(name = "ADDRESS")
@Cache(usage=CacheConcurrencyStrategy.READ_ONLY, region="employee")
public class Address {
}
That’s it, we are done. Hibernate will use the EHCache for second level caching, read Hibernate
EHCache Example for a complete example with explanation.
@Entity
@Table(name = "EMPLOYEE")
public class Employee {
@OneToOne(mappedBy = "employee")
@Cascade(value = org.hibernate.annotations.CascadeType.ALL)
private Address address;
}
Note that Hibernate CascadeType enum constants are little bit different from JPA
javax.persistence.CascadeType, so we need to use the Hibernate CascadeType and Cascade
annotations for mappings, as shown in above example.
Commonly used cascading types as defined in CascadeType enum are:
None: No Cascading, it’s not a type but when we don’t define any cascading then no operations in
parent affects the child.
ALL: Cascades save, delete, update, evict, lock, replicate, merge, and persist. Basically everything
SAVE_UPDATE: Cascades save and update, available only in hibernate.
DELETE: Corresponds to the Hibernate native DELETE action, only in hibernate.
DETATCH, MERGE, PERSIST, REFRESH and REMOVE – for similar operations
LOCK: Corresponds to the Hibernate native LOCK action.
REPLICATE: Corresponds to the Hibernate native REPLICATE action.
First-level Cache
The first-level cache is the Session cache and is a mandatory cache through which all requests must
pass. The Session object keeps an object under its own power before committing it to the database.
If you issue multiple updates to an object, Hibernate tries to delay doing the update as long as
possible to reduce the number of update SQL statements issued. If you close the session, all the
objects being cached are lost and either persisted or updated in the database.
Second-level Cache
Second level cache is an optional cache and first-level cache will always be consulted before any
attempt is made to locate an object in the second-level cache. The second level cache can be
configured on a per-class and per-collection basis and mainly responsible for caching objects across
sessions. Any third-party cache can be used with Hibernate. An org.hibernate.cache.CacheProvider
interface is provided, which must be implemented to provide Hibernate with a handle to the cache
implementation.
Query-level Cache
Hibernate also implements a cache for query result sets that integrates closely with the second-
level cache.
This is an optional feature and requires two additional physical cache regions that hold the cached
query results and the timestamps when a table was last updated. This is only useful for queries that
are run frequently with the same parameters.
</class>
</hibernate-mapping>
The usage="read-write" attribute tells Hibernate to use a read-write concurrency strategy for the
defined cache.
Cache Provider
Your next step after considering the concurrency strategies, you will use your cache candidate
classes to pick a cache provider. Hibernate forces you to choose a single cache provider for the
whole application.
Sr.No. Cache Name & Description
1 EHCache
It can cache in memory or on disk and clustered caching and it supports the
optional Hibernate query result cache.
2 OSCache
Supports caching to memory and disk in a single JVM with a rich set of
expiration policies and query cache support.
3 warmCache
A cluster cache based on JGroups. It uses clustered invalidation, but doesn't
support the Hibernate query cache.
4 JBoss Cache
A fully transactional replicated clustered cache also based on the JGroups
multicast library. It supports replication or invalidation, synchronous or
asynchronous communication, and optimistic and pessimistic locking. The
Hibernate query cache is supported.
Every cache provider is not compatible with every concurrency strategy. The following compatibility
matrix will help you choose an appropriate combination.
EHCache X X X
OSCache X X X
SwarmCache X X
JBoss Cache X X
You will specify a cache provider in hibernate.cfg.xml configuration file. We choose EHCache as our
second-level cache provider −
<?xml version = "1.0" encoding = "utf-8"?>
<!DOCTYPE hibernate-configuration SYSTEM
"http://www.hibernate.org/dtd/hibernate-configuration-3.0.dtd">
<hibernate-configuration>
<session-factory>
</session-factory>
</hibernate-configuration>
Now, you need to specify the properties of the cache regions. EHCache has its own configuration
file, ehcache.xml, which should be in the CLASSPATH of the application. A cache configuration in
ehcache.xml for the Employee class may look like this −
<diskStore path="java.io.tmpdir"/>
<defaultCache
maxElementsInMemory = "1000"
eternal = "false"
timeToIdleSeconds = "120"
timeToLiveSeconds = "120"
overflowToDisk = "true"
/>