upGrad KnowledgeHut SkillFest Sale!

Hibernate Interview Questions and Answers

Hibernate is an open-source object-relational mapping (ORM) tool for the Java programming language. It provides a framework for mapping an object-oriented domain model to a relational database. It helps developers to write code using plain Java objects and annotations to define the mapping between the Java objects and the relational database. Whether you’re preparing for a beginners' interview or appearing for advanced-level interview, our set of curated hibernate interview questions and answers will help you appear for the interview more confidently.

  • 4.7 Rating
  • 32 Question(s)
  • 20 Mins of Read
  • 1690 Reader(s)

Intermediate

POJO stands for Plain Old Java Object. Hibernate is based on the concept of taking values from Java class attributes and storing them in a database. Such classes whose objects are stored in a database are known as persistent classes. These classes have proper getter and setter methods for every property. These classes also have a default constructor. These classes should be non-final or have an interface with all the public methods declared. An ID is mandatory for each object of these classes as they will be mapped to the primary column of the table. Use of POJOs instead of simple java classes results in an efficient and well – constructed code. A simple example of a POJO class is as below:

public class Student{ 
private int id; 
private String firstName; 
private String lastName; 
private int age; 
public Employee(){} 
public Employee(String fname,String lname,int age){ 
this.firstName=fname; 
this.lastName=lname; 
this.age= age; 
} 
public int getId(){return id; } 
public void setId(int id ){ this.id = id;} 
public String getFirstName(){ return firstName;} 
public void setFirstName(String first_name){  
this.firstName=first_name; 
} 
public String getLastName(){ return lastName; } 
public void setLastName(String last_name){  
this.lastName=last_name; 
} 
public int getAge(){ return age; } 
public void setAge(int age ){ this.age= age; } 
} 

Derived properties are properties that are not mapped to any column of a database table. They are also known as calculated properties and are calculated at runtime. These properties are read-only in nature and can be defined using the @Formula annotation or by using the <formula> tag in the hbm.xml definition file. To use the @Formula annotation, we need to import org.hibernate.annotations.Formula package. 

Let us look at an example. 

@Entity 
@Table(name="EMPLOYEE") 
public class Employee implements java.io.Serializable { 
    @Id 
    @Column(name="ID") 
    private Integer id; 
    @Column(name="FIRST_NAME", length=50) 
    private String firstName; 
    @Column(name="LAST_NAME", length=50) 
    private String lastName; 
    @Column(name="MONTHLY_SALARY") 
    private float monthlySalary; 
    @Formula("MONTHLY_SALARY*12") 
        private float yearlySalary; 
    public Employee() { } 
    public Integer getId() { return id; } 
    public void setId(Integer id) { this.id = id; } 
    public String getFirstName() { return firstName; } 
    public void setFirstName(String firstName) {  
this.firstName = firstName;  
  } 
    public String getLastName() { return lastName; } 
    public void setLastName(String lastName) { this.lastName = lastName; } 
    public float getMonthlySalary() { return monthlySalary; } 
    public void setMonthlySalary(float monthlySalary) {  
this.monthlySalary = monthlySalary; 
    } 
    public float getYearlySalary() { return yearlySalary; } 
} 

In the above example, the @Formula annotation refers to the MONTHLY_SALARY column in the database table and not the monthlySalary property in the class. 

            The hbm mapping for the above class would be: 
<?xml version="1.0"?> 
<!DOCTYPEhibernate-mappingPUBLIC"-//Hibernate/Hibernate Mapping DTD 3.0//EN" 
"http://hibernate.sourceforge.net/hibernate-mapping-3.0.dtd"> 
<hibernate-mapping> 
<class name="com.other.domain.entity.Employee" table="EMPLOYEE"> 
<id name="id" type="integer" access="property"unsaved-value="null"> 
<column name="ID"/> 
<generator class="native"/> 
</id> 
<property name="firstName" type="string" column="FIRST_NAME"/> 
<property name="lastName" type="string" column="LAST_NAME"/> 
<property name="monthlySalary" type="float" column="MONTHLY_SALARY"/> 
      <property name="yearlySalary" type="float" column="YEARLY_SALARY" 
formula="(SELECT (MONTHLYSALARY*12) from EMPLOYEE e where e.id = ID)"/> 
</class> 
</hibernate-mapping> 

This is a frequently asked question in hibernate interview questions for freshers.

The Hibernate collections behave like HashMap, HashSet, TreeMap, TreeSet or ArrayList. Collection instances are like value types and are automatically persisted when referenced by a persistent object and deleted when unreferenced. There are five types of collections in Hibernate. They are: 

  1. Map  
  2. Array 
  3. List 
  4. Set 
  5. Bag

To map these collections, the type of collection must be declared from one of the following: 

  • java.util.List 
  • java.util.Set 
  • java.util.SortedSet 
  • java.util.Map 
  • java.util.SortedMap 
  • java.util.Collection 
  • or write the implementation of org.hibernate.usertype.UserCollectionType

The Hibernate mapping element used for mapping a collection depends upon the type of interface. The basic syntax for mapping is: 

<hibernate-mapping> 
<class name="<event.Class>" table="<TableName>"> 
          <id name="id" column="<ColumnName>"> 
                   <generator class="native"/> 
          </id> 
         <property name="<property>" type="<type>" column="<ColumnName>"/> 
         <property name="<property>"/> 
        <set name = “<name of set>”> 
<key column=“<column name>” not-null= “true”/> 
                       <one-to-many class=“<associated class>”/> 
        </set> 
</class> 
</hibernate-mapping> 

The <set> can be replaced with map, list etc. There are different associations for mapping the class with the corresponding table. The types of associations are as below: 

  1. one-to-many 
  2. one-to-one 
  3. many-to-one 
  4. many-to-many 

When using a map for mapping, a map-key has to be provided along with the key column.  

<map name="developmentLanguages" table="tdevelopmentlanguage" cascade="all"> 
         <key column="developer_id" not-null="true"></key> 
         <map-key type="string" column="shortname"></map-key> 
        <element column="name" type="string"></element> 
</map> 

A proxy is defined as a function which acts as a substitute to another function. When a load() method is called on session, a proxy is returned and this proxy contains the actual method to load the data. 

The session.load() method creates an uninitialized proxy object for our desired entity class. The proxy implementation delegates all property methods except for the @id to the session which will in turn populate the instance. When an entity method is called, the entity is loaded and the proxy becomes an initialized proxy object. 

Let us understand this with an example. Let us assume that there is an entity called Student. Let us also assume that initially, this entity has no connection or relation with any other tables except the Student table. When the session.load() method is called to instantiate the Student, 

Student dia = session.load(Student.class, newLong(1)); 

Hibernate will create an uninitialized proxy for this entity with the id we have assigned it and will contain no other property as we have not yet communicated with the database. However, when a method is called on dia, 

String firstName = dia.getFirstName(); 

Hibernate will fire a query to the database for information on the student with primary key 1 and populates the object dia with the properties from the corresponding row. If the row is not found, Hibernate throws an ObjectNotFoundException 

The session object is used to connect with a database. It is light-weight and is instantiated every time a database connection is required. Sessions are not thread safe and so should not be kept open for long. These objects should be created as needed and should be destroyed if not in use. Sessions hold a first-level cache of data. The org.hibernate.Session interface provides methods to insert, update and delete the object. It also provides factory methods for Transaction, Query and Criteria. 

The main functionality of Session objects is to provide create, read and delete operations to the instances of the mapped entity classes. The instances may be in one of the following states at any given point. 

  1. Transient: When an instance of a persistent class is not associated with a session, has no database representation and has no identifier value, such an instance is considered to be in the transient state 
  2. Persistent: An instance becomes persistent when it is associated with a session, has database representation and has an identifier value   
  3. Detached: An instance is detached, once the Hibernate session is closed. 

A session instance becomes serializable if its persistent class or classes is/are serialised. If a session throws an error, the transaction has to be rolled back and the session instance has to be deleted. 

A common question in hibernate interview questions and answers, don't miss this one.

The core interfaces of Hibernate framework are used to configure the application, store and retrieve objects and control transactions. The interfaces are: 

  1. Configuration: The Configuration objects are used to configure the application by setting the configuration file and mapping documents' location, retrieving the Hibernate - specific properties etc It also helps create the SessionFactory.  
  2. SessionFactory: The SessionFactory provides obtains Session instances to the application. SessionFactory instances are not lightweight, and usually, one instance is created for the whole application. If the application accesses multiple databases, it needs one per database. SessionFactory is thread-safe and can hold a second-level cache of data that is reusable between transactions at a process, or cluster, level. 
  3. Session: The Session is a persistence manager that manages operations like storing and retrieving objects. Instances of Session are inexpensive to create and destroy. Session objects are not thread-safe and have to be destroyed once their usefulness is over. Session holds a mandatory first-level cache of persistent objects that are used when navigating the object graph or looking up objects by identifier. 
  4. Query: This interface is used to query the database and control how the query execution takes place. Queries are written using HQL or in the native SQL language of the database being used. A Query instance allows for binding query parameters, limiting the number of results returned by the query and executing the query. A Query instance cannot be used outside the Session in which it has been created 
  5. Criteria: This interface is used to create and execute queries that are criteria based. Such criteria-based queries are called object-oriented criteria queries.  
  6. Transaction: A transaction represents a unit of work. When an application performs some operations on a database, it is called a transaction. We can have multiple operations within a single transaction and a single commit to commit all the operations at once. If a transaction fails or an operation fails, the transaction can be rolled back. This interface is an optional interface that the application may use or choose to handle its DB operations and transactions through its own code. 

Hibernate caching improves the performance of the application by pooling the object in the cache. It is useful when we have to fetch the same data multiple times. 

There are mainly two types of caching: first level cache and second level cache. 

  • First Level Caching:

This cache is associated with the session object and is enabled by default. It cannot be disabled. The first level cache data is not available to entire application. Hibernate provides methods which can be used to flush the cache or delete specific objects from the cache. Cached objects are not visible to the other sessions in the application and when the session is closed, all the cache objects are removed from memory. 

The session evict() method is used to remove an object from the cache. The session clear() method clears the cache entirely. The session contains() method is used to check if an object exists in the cache. It returns true if the object exists and false if it does not. 

  • Second Level Caching: 

SessionFactory object holds the second level cache data. The data stored in the second level cache will be available to entire application. But we need to enable it explicitly. 

The Hibernate architecture includes many objects such as persistent object, session factory, transaction factory, connection factory, session, transaction etc. Of these the more important ones are as below: 

  1. SessionFactory: The SessionFactory is a heavyweight object and is created when the application starts. It is created by providing it with the Configuration object which has the database configurations. If the application is using multiple databases, one SessionFactory object per database has to be created using a separate configuration file for each. The SessionFactory object configures the application using the configuration file and allows for Session object initiation. It is a thread-safe object and is used by all the threads of an application.  
  2. Session: A session object is created when the application needs a physical connection with the database. It is a lightweight object and is instantiated each time the application interacts with the database. Persistent objects are saved and retrieved through a Session object. A Session object is not thread safe and therefore should be created and destroyed as needed. 
  3. Transaction: A Transaction means an operation, or a set of operations have been performed on the database. A transaction manager monitors and handles the transactions.  This is an optional object and the application may want to use their own application code for any database operations instead of using a Transaction. The org.hibernate.Transaction interface provides methods for transaction management.  

 There can be 4 types of association mapping in hibernate. 

  1. One to One: A one-to-one association is similar to many-to-one association with a difference that the column will be set as unique. For example, an address object can be associated with a single employee object. <one-to-one> element is used to define one-to-one association. The name attribute is set to the defined variable in the parent class. The column attribute is used to set the column name in the parent table which is set to unique so that only one object can be associated with another object. 
  2. One to Many: In One-to-Many mapping association, an object can be associated with multiple objects. For example, Employee object relates to many Certificate objects. A One-to-Many mapping can be implemented using a Set java collection that does not contain any duplicate element. <one-to-many> element of set element indicates that one object relates to many other objects. 
  3. Many to One: A many-to-one association is the most common kind of association where an Object can be associated with multiple objects. For example, a same address object can be associated with multiple employee objects. <many-to-one> element is used to define many-to-one association. The name attribute is set to the defined variable in the parent class. The column attribute is used to set the column name in the parent table. 
  4. Many to Many: A Many-to-Many mapping can be implemented using a Set java collection that does not contain any duplicate element. <many-to-many> element indicates that one object relates to many other objects and column attributes are used to link intermediate column. 

Both these methods are used when the object has to be converted from detached to persistent state.The differences between update() and merge() methods are as below.

No.The update() methodmerge() method
1.Update method is called when an object needs to be edited. The method is called if the session doesn’t contain an already persistent state with the same id.Merge method is called when a persistent entity instance has to be updated with the new values from a detached entity instance

 Let's try to understand the difference by the example given below: 

...   
SessionFactory sf = obj.buildSessionFactory();   
Session s1 = sf.openSession();   
Employee e1 = (Employee) s1.get(Employee.class, Integer.valueOf(101));//passing id of employee 
s1.saveOrUpdate(e1); 
s1.close(); 
e1.setSalary(70000);   
Session s2 = sf.openSession();   
Employee e2 = (Employee) s2.get(Employee.class, Integer.valueOf(101));//passing same id 
Transaction tx=s2.beginTransaction();   
s2.update(e1); //throws exception 
s2.merge(e1);   
tx.commit();   
s2.close();   

In a single session, only one persistent object can be maintained with a specific primary key. In the above example, the Employee object e1 is stored in the session cache. When the session is closed, e1 will be converted to detached state. If we have to update the Employee object e1 with the new values, we need another session. In the second session, if we try to update e1, an exception is thrown. Now we will call merge in session2 and changes of e1 will be merged in e2 as e2 has the same id as e1. 

 Hibernate configuration file: This file contains a set of configuration settings related to the database and other related parameters which is required by Hibernate for connecting to the database. This file is placed in the root directory of the application’s classpath. Some properties that are configured in this file are: 

  • hibernate.connection.driver_class: which is the JDBC driver class for database connection 
  • hibernate.connection.url: which is the url to the database instance 
  • hibernate.connection.username: is the username to the database instance 
  • hibernate.connection.password: is the password to the database instance 
  • hibernate.connection.autocommit: is to allow autocommit mode to the JDBC connection 

Hibernate Mapping file: This file contains the mapping of a POJO class to the table. Giving the POJO class the same name as the table and having class properties corresponding to the column names helps in avoiding confusions while mapping the class properties to the table columns.An object normally contains 3 properties - identity, state and behavior. The identity and behavior of the object has to be avoided when storing the object state (value) in the database. This is taken care of by mapping. A Hibernate application can have multiple mapping files for mapping the classes to the tables.Mapping can be done using XML or Annotations. Syntax for creating a mapping file in XML is as below: 

<hibernate-mapping> 
<class name="POJO class name" table="table name in database"> 
                            <id name="variable name" column="column name in database" type="java/hibernate type" /> 
                            <property name="variable1 name" column="column name in database" type="java/hibernate type" /> 
                            <property name="variable2 name" column="column name in database" type="java/hibernate type" /> 
                   </class> 
<hibernate-mapping> 

It's no surprise that this one pops up often in hibernate tricky interview questions.

Using Hibernate Annotations has the following drawbacks: 

  • Annotations are included in the code and any changes made to the Annotations lead to code recompilation whereas an XML mapping file is placed outside the code file. So changes can be made without recompilation 
  • If migrating from a legacy environment like Hibernate 2 or Hibernate 3, the pre-existing POJO source code need not be altered due to it using XML mapping and working well which means you will not inject known good code with possible bugs. 
  • Using Annotations does not separate behavior and the POJO class. All information is in a single file. 
  • Some annotations can cause lifecycle mismatches and should be avoided. 
  • Some examples of bad annotations are ORM mapping, database configuration, hard-coded config for items that may vary between deployment environments, validations that may vary depending on context. 

Let us look at a simple scenario. As we know every bit of data, be it source code, a compiled class, an object, or anything has a lifecycle associated with it. Suppose we add Hibernate Annotations to our Java code especially if we are connecting to a database and are expecting only this class to connect to the database. The table columns are mapped to the class using the annotations. Now let us assume that we use this class in an API and have consumed the API in a different project. Now the annotations we had used will leak into our API causing mismatches as the database and the tables are different. So, we end up using mapping tools to translate between different layers of the beans in a system. This is an example of the disadvantages of using annotations. 

The highlighted line defines “cascade=Cascade Type.ALL” and it essentially means that any change that happens to Employee Entity must cascade to all associated entities (Accounts Entity in this case) also. This means that if you save an employee into the database, then all associated accounts will also be saved into the database. If an Employee is deleted, then all accounts associated with that Employee will also be deleted. But if we want to cascade only the save operation but not the delete operation, we need to clearly specify it using below code. 

@OneToMany(cascade=CascadeType.PERSIST, fetch = FetchType.LAZY) 
@JoinColumn(name="EMPLOYEE_ID"private Set<AccountEntity> accounts; 

Now only when the save() or persist() methods are called using employee instance, will the accounts be persisted.If any other method is called on session, its effect will not affect/cascade to the accounts entity. 

One of the main aspects of JPA is that it helps to propagate Parent to Child relationships. This behavior is possible through CascadeTypes. The CascadeTypes supported by JPA are:  

  1. CascadeType.PERSIST : This cascade type means that save() or persist() operations cascade from the parent or owning entity to related entities. 
  2. CascadeType.MERGE :This cascade type means that related entities are merged when the parent or owning entity is merged. 
  3. CascadeType.REFRESH : This cascade type refreshes the related entities when the owning or parent entity calls the refresh() operation. 
  4. CascadeType.REMOVE : This cascade types removes all related entities associations when the owning entity is deleted. 
  5. CascadeType.DETACH : This cascade type detaches all related entities if a “manual detach” occurs. 
  6. CascadeType.ALL : When all the cascade operations have to be applied to the owning or parent entity, the cascade type all is used. 

The cascade configuration option accepts an array of CascadeTypes. The below example shows how to add the refresh and merge operations in the cascade operations for a One-to-Many relationship: 

@OneToMany(cascade={CascadeType.REFRESH, CascadeType.MERGE}, fetch = FetchType.LAZY) 
@JoinColumn(name="EMPLOYEE_ID"private Set<AccountEntity> accounts; 

Cascading is useful only for Parent - Child associations where the parent entity state transitions cascade to the child entity.  

Hibernate needs information for mapping the POJO classes and their properties with the tables and their columns in the database. The configuration settings for this mapping are done through annotations or through XML configuration file. The XML mapping document defines the mapping between the properties of the POJO classes and the corresponding table columns in the database. Below is the syntax for the XML mapping document. 

<?xml version="1.0"?> 
 <!DOCTYPE hibernate-mapping PUBLIC 
 "http://hibernate.sourceforge.net/hibernate-mapping-2.0.dtd"> 
<hibernate-mapping> 
 <class name=“name of the persistence class or POJO class” table=“The table name from the database”> 
 <id name="id" column= “column name”> 
 <generator class="increment"/> 
 </id> 
 <property name="text" column="Persistance_message"/> 
 <many-to-one name="name of the relationship" cascade="cascade type" column="column name"/> 
 </class> 
</hibernate-mapping> 

The tag <hibernate-mapping> is the main tag for an xml mapping document. This tag specifies that this document has the mapping details between the persistent class and the table columns. Using XML mapping document avoids a full redeploy where the entire application has to be recompiled which would be the case if annotations were used. Annotations are ideal when the object model is persisted in the same way every time. Annotations become a liability if the code is used as an API where the mappings will change. In such situations, XML mapping is the answer. Another advantage to XML mapping is that it keeps the POJO class and its behavior separate. 

JPA annotations are used to map Java persistent classes with their corresponding tables in the database. Hibernate is one of the more popular implementations of the JPA specifications. All the JPA annotations are defined in the javax.persistence package. Along with JPA annotations, Hibernate also supports some other annotations which are available in org.hibernate.annotations package. Some of the important annotations are: 

  1. javax.persistence.Entity: This is used with POJO classes to specify that they are entity beans. 
  2. javax.persistence.Table: This is used with entity beans to define the corresponding table name in database. 
  3. javax.persistence.Access: This is used to define the access type, either field or property. Default value is field and if you want hibernate to use getter/setter methods then you need to set it to property. 
  4. javax.persistence.Id: This is used to define the primary key in the entity bean. 
  5. javax.persistence.EmbeddedId: This is used to define composite primary key in the entity bean. 
  6. javax.persistence.Column: This is used to define the column name in database table. 
  7. javax.persistence.GeneratedValue: This is used to define the strategy to be used for generation of primary key. It is used along with javax.persistence.GenerationType enum. 
  8. javax.persistence.OneToOne: This is used to define the one-to-one mapping between two entity beans. Other similar annotations are OneToMany, ManyToOne and ManyToMany 
  9. org.hibernate.annotations.Cascade: This is used to define the cascading between two entity beans, used with mappings. It works in conjunction with org.hibernate.annotations.CascadeType 
  10. javax.persistence.PrimaryKeyJoinColumn: This is used to define the property for foreign key. It is used along with org.hibernate.annotations.GenericGenerator and org.hibernate.annotations.Parameter 

Advanced

A common question in hibernate interview questions for experienced, don't miss this one.

Concurrency strategies act as mediators. They are responsible for storing items and retrieving them from the cache. If the developer wants to enable a second-level cache, the developer must decide to do it for each persistent class and collection. The developer must also decide which cache concurrency has to be implemented.  

The concurrency strategies that the developer can implement are as follows: 

  • Transactional: This strategy is used to read data where it is critical to prevent stale data in concurrent transactions, especially in case of an update. 
  • Read - Only: This strategy is compatible with the reference data i.e. the data that can’t be modified. 
  • Read - Write: This strategy is similar to a transactional strategy, where it is critical to prevent stale data. 
  • Non-strict-Read-Write: There is no guarantee of consistency between the database and cache when this strategy is used. This strategy is used only if data is modifiable and a small amount of stale data is not a critical concern. 

These strategies are used with second - level cache. An example of the usage of these strategies is shown in the below example, where we add a mapping element to the configuration file to inform Hibernate to cache the persistent class instances using the read-write strategy. We are using the Employee class in this example. 

<hibernate-mapping> 
          <class name = "Employee" table = "EMPLOYEE"> 
                <meta attribute = "class-description"> 
                    This class contains the employee detail.  
                </meta> 
                <cache usage = "read-write"/> 
                <id name = "id" type = "int" column = "id"> 
                    <generator class="native"/> 
                </id> 
                <property name = "firstName" column = "first_name" type = "string"/> 
                <property name = "lastName" column = "last_name" type = "string"/> 
                <property name = "salary" column = "salary" type = "int"/> 
         </class> 
     </hibernate-mapping> 

Hibernate has a feature to monitor all persistent object properties. Whenever an entity is loaded through hibernate, it makes an additional copy of that whole entity object along with all the entity's property values. Irrespective of a change in one property or multiple properties, Hibernate checks all the objects properties. It detects which objects have been modified and then calls update statements on all updated objects. Once the changes or modifications are identified, a transaction is performed using the session object. So, if a session object is open and an object property is modified, the data is synchronized in the database. The data will be synchronized but will not be committed, till the session object's commit() method or flush() method is called. Both synchronization and committing of code will happen together when the commit method is called. This process of monitoring all the persistent or managed objects and updating only the changed object properties is called automatic dirty checking. Dirty checking helps the user or developer to avoid the time-consuming database write actions. This feature makes necessary updates or changes to the fields based on the changes made to the objects of the mapped class and the remaining fields are left unchanged or untouched.

This is a frequently asked hibernate interview questions and answers for experienced

EHCache is the best choice for utilizing hibernate second level cache. Following steps are required to enable EHCache in hibernate application. 

  • Add hibernate-ehcache dependency in your maven project, if it’s not maven then add corresponding jars. 
<dependency> 
        <groupId>org.hibernate</groupId> 
        <artifactId>hibernate-ehcache</artifactId> 
        <version>4.3.5.Final</version> 
</dependency> 
  • Add below properties in hibernate configuration file.
<property name="hibernate.cache.region.factory_class">org.hibernate.cache.ehcache.EhCacheRegionFactory</property> 
<!-- For singleton factory --> 
<!-- <property name="hibernate.cache.region.factory_class">org.hibernate.cache.ehcache.SingletonEhCacheRegionFactory</property> 
--> 
<!-- enable second level cache and query cache --> 
<property name="hibernate.cache.use_second_level_cache">true</property> 
<property name="hibernate.cache.use_query_cache">true</property> 
<property name="net.sf.ehcache.configurationResourceName">/myehcache.xml</property> 
  • Create EHCache configuration file, a sample file myehcache.xml would look like below.
<?xml version="1.0" encoding="UTF-8"?> 
<ehcache xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" 
xsi:noNamespaceSchemaLocation="ehcache.xsd"updateCheck="true" 
monitoring="autodetect"dynamicConfig="true"> 
    <diskStorepath="java.io.tmpdir/ehcache" /> 
    <defaultCachemaxEntriesLocalHeap="10000"eternal="false" 
timeToIdleSeconds="120"timeToLiveSeconds="120"diskSpoolBufferSizeMB="30" 
maxEntriesLocalDisk="10000000"diskExpiryThreadIntervalSeconds="120" 
memoryStoreEvictionPolicy="LRU"statistics="true"> 
        <persistence strategy="localTempSwap" /> 
    </defaultCache> 
    <cache name="employee" maxEntriesLocalHeap="10000"eternal="false" 
timeToIdleSeconds="5"timeToLiveSeconds="10"> 
        <persistence strategy="localTempSwap" /> 
    </cache> 
    <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.Cacheimport org.hibernate.annotations.CacheConcurrencyStrategy; 
@Entity 
@Table(name = "ADDRESS") 
@Cache(usage=CacheConcurrencyStrategy.READ_ONLY, region="employee") 
public class Address { 
} 

Hibernate will now use the EHCache for second level caching.

Cascading means when an insert, update or delete operation occurs on one entity, its related entities also are inserted, updated or deleted. If cascading is not used, the objects will have to be saved independently and explicitly.

import org.hibernate.annotations.Cascade; 
@Entity 
@Table(name = "EMPLOYEE"public class Employee {  
@OneToOne(mappedBy = "employee") 
@Cascade(value = org.hibernate.annotations.CascadeType.ALL) 
public Department dept; 
} 

The CascadeTypeenum constants of Hibernate are slightly different from JPA. As shown in the above example, we use. CascadeType and Cascade annotations for mappings. The commonly used cascading types as defined in CascadeTypeenum are: 

  1. None: There is no cascading as no cascading is defined. This means that operations in the parent do not affect the child. 
  2. ALL: This includes all the cascade types i.e. save, delete, update, evict, lock, replicate, merge and persist. This also means that any operation on the parent will affect the child as well 
  3. SAVE_UPDATE: Available only in hibernate. Includes the Cascade save and update 
  4. DELETE: This type corresponds to the Hibernate native DELETE action. 
  5. DETACH, MERGE, PERSIST, REFRESH and REMOVE – These also correspond to similar Hibernate native actions 
  6. LOCK: Also corresponds to the Hibernate native LOCK action. 
  7. REPLICATE: This also corresponds to the Hibernate native REPLICATE action. 

Validating data is an integral part of any application and happens in all the application layers. Most of the time, the same validations are replicated across the layers making it error-prone and time-consuming. To avoid duplication of the validation logic, JSR 380 defines a metadata model and API for data validation i.e. entity and method validation. Hibernate Validator is the reference implementation of JSR380. When Hibernate Validator is used in an application, it will also require an implementation of the Unified Expression Language (JSR341) for evaluating dynamic expressions as well as the Hibernate Validator dependencies. Let us understand the Hibernate Validator with an example:

<dependency> 
<groupId>javax.validation</groupId> 
<artifactId>validation-api</artifactId> 
<version>1.1.0.Final</version> 
</dependency> 
<dependency> 
<groupId>org.hibernate</groupId> 
<artifactId>hibernate-validator</artifactId> 
<version>5.1.1.Final</version> 
</dependency>

 Let us create an Employee class:  

import javax.validation.constraints.Min; 
import javax.validation.constraints.NotNull; 
import javax.validation.constraints.Size; 
import org.hibernate.validator.constraints.CreditCardNumber; 
import org.hibernate.validator.constraints.Email; 
public class Employee { 
@Min(value=1, groups=EmpIdCheck.class) 
private int id; 
@NotNull(message="Name cannot be null") 
@Size(min=5, max=30) 
private String name; 
@Email 
private String email; 
@CreditCardNumber 
private String creditCardNumber; 
    //default no-args constructor 
public Employee(){} 
public Employee(int id, String name, String email, String ccNum){ 
 this.id=id; 
 this.name=name; 
this.email=email; 
this.creditCardNumber=ccNum; 
    } 
public int getId() { 
return id; 
    } 
public void setId(int id) { 
 this.id = id; 
    } 
public String getName() { 
return name; 
    } 
public void setName(String name) { 
 this.name = name; 
    } 
public String getEmail() { 
return email; 
    } 
public void setEmail(String email) { 
this.email = email; 
    } 
public String getCreditCardNumber() { 
return creditCardNumber; 
    } 
public void setCreditCardNumber(String creditCardNumber) { 
this.creditCardNumber = creditCardNumber; 
    } 
} 

Hibernate validator provides very good validation annotations like @Email and @CreditCardNumber which avoids usage of implementation specific annotations which lead to loose coupling. 

Hibernate Validator also allows us to define Custom Error Messages which we can configure in the ValidationMessages.properties file in the classpath. The file looks like: 

#Hibernate Bug for @CreditCardNumber Workaround - https://hibernate.atlassian.net/browse/HV-881 
org.hibernate.validator.constraints.LuhnCheck.message=The check digit for ${validatedValue} is invalid, Luhn Modulo 10 checksum failed. 
org.hibernate.validator.constraints.Email.message=Invalid email address 

An exception is an error which is generated at run-time and interrupts the program flow. An exception can be generated due to a number of reasons. One of the reasons could be entering of invalid data, or a necessary file is not found or the exception could be due to network issues etc. 

 The exceptions are handled by the Entity Manager which calls the close() method. This method discards any changes made and rolls back the database transaction. The Entity Manager handles core exceptions like:  

  • IllegalArgumentException: Wrong argument, or failing to recognize argument, or having the incorrect format, or incorrect number of arguments etc. 
  • EntityNotFoundException: An Entity was expected but did not match the requirement, or an Entity was expected but was not passed 
  • TransactionRequiredException: A Transaction is expected but is not found. This exception occurs due to missing Transaction object 
  • IllegalStateException: Wrong way of using the Entity Manager 

When Hibernate interacts with the database it throws SQLException. Hibernate provides better exception handlers than the JDBCException. Developers can use the try and catch block to handle the exceptions. The line of code that may cause an exception is enclosed in a try block and according to the exception thrown, the exception handler is added in the catch block. In the below example, the code for data updating is enclosed in the try block which will be handled by Hibernate Exception in catch block. 

Example.java 

importcom.hibernate.exception.handling.model.Student; 
importcom.hibernate.exception.handling.util.HibernateUtil; 
importorg.hibernate.HibernateException; 
importorg.hibernate.Session; 
importorg.hibernate.Transaction; 
publicclassHibernateUpdate { 
publicstaticvoidmain(String args[]) { 
Session sessionObj = HibernateUtil.getSessionFactory().openSession(); 
introll = 5; 
Transaction transactionObj = sessionObj.beginTransaction(); 
Student studentObj = (Student) session.load(Student.class, roll); 
try{ 
studentObj.setName("Java Code Geek"); 
studentObj.setCourse("Hibernate"); 
sessionObj.merge(studentObj); 
transactionObj.commit(); 
System.out.println("Update Successfully"); 
sessionObj.close(); 
} catch(HibernateExceptionhibernateEx) { 
try{ 
transactionObj.rollback(); 
} catch(RuntimeExceptionruntimeEx){ 
System.err.printf("Couldn’t Roll Back Transaction", runtimeEx); 
} 
hibernateEx.printStackTrace(); 
} finally{ 
if(sessionObj!= null) { 
sessionObj.close(); 
} 
} 
} 
} 

Note: Any exceptions thrown by the Hibernate framework are FATAL, hence developers have to rollback the transaction and close the current session object immediately.  

The LazyInitializationException is thrown when trying to access a relationship with another entity which is not initialized and without an active session. The below simple code snippet explains this reason. 

Example.java 

EntityManagerem = emf.createEntityManager(); 
em.getTransaction().begin(); 
Author a = em.find(Author.class, 1L); 
em.getTransaction().commit(); 
em.close(); 
logger.info(a.getFirstName() + " "+ a.getLastName() + " wrote "+a.getBooks().size() + " books."); 

The best way to fix a LazyInitializationException is to initialize the required relationship in the business tier. It is also not advisable to initialize all relationships just because there might be one client out there who needs one of them. For performance reasons, you should only initialize the relationships you need. 

A staple in hibernate interview questions for experienced professionals, be prepared to answer this one.

Hibernate supports the three basic inheritance mapping strategies: 

  • table per class hierarchy 
  • table per subclass 
  • table per concrete class 

1. Table per class Hierarchy 

Let us assume we have an interface Payment which is implemented by classesCreditCardPayment, CashPayment, andChequePayment. When we map using the table per hierarchy mapping strategy, the xml would be written as below:: 

<class name="Payment" table="PAYMENT"> 
    <id name="id" type="long" column="PAYMENT_ID"> 
        <generator class="native"/> 
    </id> 
    <discriminator column="PAYMENT_TYPE" type="string"/> 
    <property name="amount" column="AMOUNT"/> 
    ... 
    <subclass name="CreditCardPayment" discriminator-value="CREDIT"> 
        <property name="creditCardType" column="CCTYPE"/> 
        ... 
    </subclass> 
    <subclass name="CashPayment" discriminator-value="CASH"> 
        ... 
    </subclass> 
    <subclass name="ChequePayment" discriminator-value="CHEQUE"> 
        ... 
    </subclass> 
</class> 

In this strategy, exactly on table is required. The restrictions or limitations based on this strategy is that the subclass properties cannot have NULL values. 

2. Table per subclass 

A table per subclass mapping looks like this: 

<class name="Payment" table="PAYMENT"> 
    <id name="id" type="long" column="PAYMENT_ID"> 
        <generator class="native"/> 
    </id> 
    <property name="amount" column="AMOUNT"/> 
    ... 
    <joined-subclass name="CreditCardPayment" table="CREDIT_PAYMENT"> 
        <key column="PAYMENT_ID"/> 
        <property name="creditCardType" column="CCTYPE"/> 
        ... 
    </joined-subclass> 
<joined-subclass name="CashPayment" table="CASH_PAYMENT"> 
        <key column="PAYMENT_ID"/> 
        ... 
    </joined-subclass> 
    <joined-subclass name="ChequePayment" table="CHEQUE_PAYMENT"> 
        <key column="PAYMENT_ID"/> 
        ... 
    </joined-subclass> 
</class> 

In this strategy four tables are required i.e. 1 superclass and 3 subclasses. The three subclass tables are associated with the superclass table through the Primary Key. So this relational model is actually a one-to-one association between the superclass and subclasses. 

3. Table per concrete class 

We can map the table per concrete class strategy by using <union-subclass>. 

<class name="Payment"> 
    <id name="id" type="long" column="PAYMENT_ID"> 
        <generator class="sequence"/> 
    </id> 
    <property name="amount" column="AMOUNT"/> 
    ... 
    <union-subclass name="CreditCardPayment" table="CREDIT_PAYMENT"> 
        <property name="creditCardType" column="CCTYPE"/> 
        ... 
    </union-subclass> 
    <union-subclass name="CashPayment" table="CASH_PAYMENT"> 
        ... 
    </union-subclass> 
    <union-subclass name="ChequePayment" table="CHEQUE_PAYMENT"> 
        ... 
    </union-subclass> 
</class> 

3 tables are mapped to the subclasses. Each table defines columns for all properties of the class, including inherited properties. The limitation of this strategy is that if a property is mapped on the superclass, the column name must be the same on all subclass tables. Another limitation is that the identity generator strategy is not allowed in union subclass inheritance. The primary key has to be shared across all unioned subclasses of a hierarchy. If the superclass is abstract, then the mapping must show it as abstract with abstract="true". If it is not abstract, an additional table is required to hold the instances of the superclass. 

Hibernate uses a language called HQL (Hibernate Query Language) which is an Object-oriented query language and works with persistent objects and their properties. Queries written in HQL are translated by Hibernate into SQL which is the language understood by the database which is being queried. Even though Hibernate supports SQL statements written in native SQL, it is advisable to use HQL as it helps take advantage of Hibernate's SQL generation and caching strategies.  

Some methods of Query interface: 

  • To create a new instance of Query for a HQL string we use the session.createQuery(String queryStringmethod.  
String queryString = "select * from DEPARTMENT" 
Query query = session.createQuery(queryString); 
List list    = query.list(); 
  • To filter collections (which is the result of a query) based on a filter string, the session.createFilter(Object collection, String filterStringis used. 
Collection<Child> childs = parent.getChilds(); 
Query query = session.createFilter(childs," where this.name like 'S%'"); 
List list = query.list(); 
  • To create a criteria, the method session.createCriteria(Class persistentClassis used 
Criteria criteria=session.createCriteria(Parent.class); 
criteria.add(Restrictions.like("name","S%"); 
List list=criteria.list(); 
The method session.createSQLQuery(String queryString) is used to create SQL queries using Native SQL. 
String sqlString="SELECT * FROM PARENT where name like 'S%'"; 
SQLQuery sqlQuery=session.createSQLQuery(sqlString); 
List list= sqlQuery.list(); 

Hibernate aggregate functions are functions which calculate the result of all the object property values which satisfy a given query condition or criteria. These functions are used in a HQL query which supports various functions like min(), max(), sum(), avg() and count() in the SELECT statement. 

Assume that an entity named Student has been created which has been mapped to its corresponding table in the database. 

  • To find the minimum age among all students, we can write a function as below: 
@Test 
public void whenMinAge_ThenReturnValue() { 
    int minAge = (int)session.createQuery("SELECT min(age) from Student") 
      .getSingleResult(); 
assertThat(minAge).isEqualTo(20); 
} 

The getSingleResult() method returns an Object. Since we need an integer, the method has been downcast to int 

  • To find the maximum age, we can write a function similar to the one we wrote for min() 
@Test 
public void whenMaxAge_ThenReturnValue() { 
    int maxAge = (int)session.createQuery("SELECT max(age) from Student") 
      .getSingleResult(); 
assertThat(minAge).isEqualTo(20); 
} 
  • To get the sum of all ages, we can use the sum() function 
@Test 
public void whenSumOfAllAges_ThenReturnValue(){ 
    double sumOfAllAges = (double)session.createQuery("SELECT sum(age) from Student") 
      .getSingleResult(); 
assertThat(minAge).isEqualTo(20); 
} 

Depending on the result, the method is downcast to either long or double 

  • The avg() function is similar to sum. The avg() function always returns a double.  
  • The count() function is used to count the number of records. The count can also be based on a condition or criteria. 
@Test 
public void whenCountAll_ThenReturnValue() { 
    Long totalStudents = (Long) session.createQuery("SELECT count(*) from Student") 
      .getSingleResult(); 
assertThat(totalStudents).isEqualTo(5); 
} 

The count() always returns a Long.  

The Generator class is used to generate ids for the persistent class objects. These unique ids are inserted into the mapped table as primary key values. All the generator classes implement the org.hibernate.id.IdentifierGenerator interface. The default generator classes provided by the Hibernate Framework are as below: 

  1. Assigned: is supported by all databases and is the default generator class 
  2. Increment: is supported by all databases and uses the formula of max id value of database + 1 
  3. Sequence: is not supported in MySQL. It reads next value of a database sequence and then returns that value as id to the hibernate. If there is no sequence in the database, it uses the default sequence 
  4. Hilo: is used to generate ids of types short, int and long. It uses the low and high algorithm. Hilo is a shortcut name for the TableHiloGenerator class.  
  5. Native: It uses the identity, sequence or hilo generator classes to generate ids depending on the type of database. 
  6. Identity: it is used in databases like Sybase, MS SQL etc to support the id column. The id that is returned is of type short, int or long. The database has the responsibility of generating the unique identifier.   
  7. uuid: UUID stands for Universal Unique Identifier and is a shortcut name for AbstractUUIDGenerator class. This generates a string of 32 characters based on the starting time of the JVM, IP address of the machine, Counter value of the JVM and the system time.  
  8. foreign: This generator class is used in only one – to – one relationship. It returns the id of the parent as the id of the child. 

Of the above classes, assigned, increment, sequence, hilo, native, foreign and identity are used for int, long and short types of primary keys, whereas uuid is used for string type of primary keys (varchar2).  

Java Persistence API (JPA) provides a collection of classes and methods that can be used to persistently store large amounts of data into a database. ORM or Object-Relational Mapping is one way to implement JPA. JPA bridges the gap between object model (Java code) and the relational model (database). It reduces the burden of interacting with the database significantly. 

JPA provides an ORM layer through frameworks like Hibernate ORM which generates the required code for object-relational mapping. Here, the classes become the table names and the fields (properties) become the table columns. Several implementations are available for JPA. The more popular of these are Hibernate, EclipseLink and Apache OpenJPA. Using JPA, a developer can work directly with objects as opposed to working with SQL statements which is why JPA implementation is also called as Persistence Provider. Persistence Metadata is where the mapping between Java objects and database tables is defined. 

The JPA provider will use this metadata information to perform the correct database operations. The JPA metadata can be defined using annotations in the Java class or through XML. It could also be a combination of both depending on the necessity. If there is an XML configuration, it will take priority and overwrite the annotations. JPA specifications are defined in the java.persistence package. 

Transaction is a single unit of work. It is single-threaded and abstracts the application from the underlying JDBC or JTA transaction. A transaction is associated with a session. It is instantiated by calling the session.beginTransaction() method. The transaction interface has the following methods: 

  1. void begin(): starts a new transaction 
  2. void commit(): ends a transaction. It does not work if the mode is FlushMode.NEVER 
  3. void rollback(): rolls back a transaction to the last commit forcefully 
  4. void setTimeout(int seconds): it sets a timeout for any transaction that is started by a call to begin the transaction on the particular instance. 
  5. booleanisAlive(): it returns a true or false and checks if the transaction is still alive. 
  6. void registerSynchronization(Synchronization s): this method registers a user synchronization callback for the transaction. 
  7. booleanwasCommited(): returns a true or false and checks if the transaction has been commited successfully. 
  8. booleanwasRolledBack(): returns a true or false and checks if the transaction rollback was successful. 

Every transaction has a set of properties called ACID properties. ACID stands for Atomicity, Consistency, Isolation, Durability. 

Expect to come across this popular question in hibernate advanced interview questions.

Hibernate’s session class has 2 popular methods get() and load(), to access an object. These 2 methods are similar in the work they do but have very subtle differences. The differences are as follows: 

  1. If an object is not found based on the id passed to it, the get() method will return a null, whereas the load() method will throw an exception. It throws the ObjectNotFound exception. 
  2. When using load() method, information other than the id can be retrieved from the proxy, whereas get() will always hit the database for any information.  
  3. If the developer is sure of the object’s existence, it is always preferable to use load() as it returns the information faster and without contacting the database. If the object’s existence is doubtful, it is preferable to use get() as it will return a null if it cannot find the object but will be slower if the object does exist as it will contact the database for information. 
  4. If an object is found, get() method will return a fully initialized object, whereas the load() method will return the object with the Id but may not initialize the other properties of the object. If you require an object with just the Id to create a relationship, use the load()method 

Persistent entities in Hibernate can be in any of the below states: 

  1. Transient: Objects or entities which are not yet associated with any Hibernate session or have been mapped to any database tables are considered to be in the Transient state. These objects exist in the Heap. These objects are said to be in the new state. When in this state an Object will not have an identifier. To persist these objects, save, persist or saveOrUpdate methods have to be used. 
  2. Persistent: When an object is associated with a database table, it is said to be in persistent state. A Persistent object is managed by the current persistence context. Any change made to this object is propagated in the database with which the object is associated. Associating a transient entity with a session will make it persistent  
  3. Detached: An object or entity is said to be in the detached state when the persistence context it is associated with is closed. In this state, any changes made to the object are not tracked and the database with which it is associated, is not synchronized automatically. A detached object can be reattached to a persistence context if and only if there is no other object associated with the database row in the current Hibernate session.  
  4. Removed: When persistent objects are handed over to remove() method, they are said to be in the Removed state. These objects are only marked for removal. 

Every entity in Hibernate has to have a field which maps to the primary key of a table in a database. Such a field is identified by the @Id annotation. Such a field is also known as the identifier field. Identifiers are of two types: Simple Identifiers and Generated Identifiers. 

Simple Identifiers: This is the most straightforward way of mapping. The mapping is done by using the @Id annotation. Simple identifiers map to a single property of the below types: 

  • Any Java primitive type 
  • Any primitive wrapper class type 
  • java.lang.String 
  • java.util.Date 
  • java.sql.Date 
  • java.math.BigDecimal 
  • java.math.BigInteger 

Let us look at a small example: 

@Entity 
publicclassStudent { 
    @Id 
    privatelongstudentId; 
    //constructors, getters, setters 
} 

Generated Identifiers: When the primary key values have to be generated automatically, @GeneratedValue annotation is added. Generated identifiers are of 4 types: 

  • Auto: This is the default generation type. Values are determined based on the types of the primary key value. 
  • Identity: This type is dependent on the IdentityGenerator which expects auto-incremented or auto generated identity column values from the database 
  • Sequence: A class named SequenceStyleGenerator is provided by Hibernate to work with sequence – based id. This generator uses sequences if they are supported by the database. 
  • Table: This type of generator generates values by using the underlying database table. 

Description

Hibernate is a Java framework. It is a lightweight, open-source Object Relational Mapping tool (ORM). It is used to generate persistence logic, that is, it is used to store and process data for long use. Here, we have brought together the most frequently asked Hibernate interview questions to familiarize you with the skills and knowledge required to succeed in your next Hibernate job interview. If you want to learn more about Hibernate, enroll in our Hibernate Course and learn more about it. 

Here are some of the world’s most popular and top-rated organizations that are using Hibernate:

  1. Bodybuilding.com 
  2. StyleShare Inc. 
  3. Peewah 
  4. Zolkin 
  5. Zendy Health, etc. 

Hibernate integrates with Java, AnyChart, and TimescaleDB. If you are looking to build your career in the field of Hibernate, then begin by choosing a Hibernate Training program and start a career as a Java Architect-Hibernate, Java Developer-Hibernate, Java Lead Hibernate, etc.

Taking up a training program will help you attain various skills, which will be an advantage. A Java Developer with Hibernate skills has an average pay of US$78,195 per year, with experienced Java Developers with Hibernate skills earning as high as US$108,000. If you want to learn vastly about computer programming training courses, you can join KnowledgeHut to upskill your career today. 

These Hibernate interview questions and answers have been designed in such a manner that they will get you familiarized with the nature of questions that you might face during your interview and will help you to crack Hibernate Interview easily & acquire your dream career as a Java Architect-Hibernate, Java Developer-Hibernate, Java Lead-Hibernate, etc. These highly rated Hibernate interview questions will surely boost your confidence to face an interview and prepare you to answer your interviewer’s questions best. The experts suggest these interview questions on Hibernate.

Wish you all the luck and confidence!

Read More
Levels