Hibernate / Hibernate interview questions
Lazy loading.
@NotNull
CharSequence, Collection, Map or Array object cannot be null, however can be empty.
@NotEmpty
The CharSequence, Collection, Map or Array object cannot be null and not empty (size > 0).
@NotBlank
The string is not null and the length is greater than zero.
Here are the examples: String test = null; @NotNull: false @NotEmpty: false @NotBlank: false String test = ""; @NotNull: true @NotEmpty: false @NotBlank: false String test = " "; @NotNull: true @NotEmpty: true @NotBlank: false String name = "Some text"; @NotNull: true @NotEmpty: true @NotBlank: true
load() | get() |
Only use the load() method when the object exists in DB | use get() if you are unsure about the existence of object. |
load() method throws an exception if the unique identifier could not be found. | get() method returns null if the unique identifier not found in the database |
load() returns a proxy and will not hit database unil the proxy is invoked to access properties. | get() will hit the database always. |
Save()
- Returns generated Id after saving. The return type is serializable.
- Saves the value to DB immediately and keeps track of the entity until the end of the session(I have tried to change the entity values outside of the transaction, it does not show any effect when session commits)
- Does not save the changes to the db outside of the transaction.
- Assigns the generated id to the entity you are persisting
- Session.save() for a detached object will create a new row in the table.
Persist()
- Does not returns generated Id after saving. Its void return type.
- Saves the value to DB immediately and keeps track of the entity until the end of the session.(I have tried to change the entity values outside of the transaction, it does not show any effect when session commits)
- Does not save the changes to the db outside of the transaction.
- Assigns the
generated id
to the entity you are persisting session.persist()
for a detached object will throwPersistentObjectException
as it is not allowed.
Hibernate Query Language is known as an object oriented query language. It is like structured query language (SQL).
- You don't need to learn SQL
- Database independent
- Simple to write query
Hibernate offers a query language that embodies a very powerful and flexible mechanism to query, store, update, and retrieve objects from a database. This language, the Hibernate query Language (HQL), is an object-oriented extension to SQL.
There are 3 different ways we can create a SQL query in Hibernate.
- session.createQuery()
- session.createSQLQuery()
- session.createCriteria()
Session.createQuery()
creates Query object using the HQL syntax. For example:
Query query = session.createQuery("from Student s where s.name like 'k%'");
Session.createSQLQuery()
Creates Query object using the native SQL syntax. For example:
Query query = session.createSQLQuery("Select * from Student");
Session.createCriteria()
Criteria object for setting the query parameters.
This feature help user to create queries without writing any SQL or HQL.
@UniqueConstraint and unique attribute of @Column instructs schema/DDL generation tool to generate the corresponding unique constraints however using that attributes on POJO doesn't implement constraints itself.
@Entity @Table(uniqueConstraints= @UniqueConstraint(columnNames = {"email", "empl_id"})) public class EntityClass { ... }
@Entity @Table(name="USER_TABLE") public class User{ @Id @Column(name = "ID") private String id; @Column(name = "SSN", unique=true) private String ssnumber;
The most common methods of Hibernate configuration are:
- Programmatic configuration
- XML configuration (using hibernate.cfg.xml)
- Annotations
ORM stands for object/relational mapping. ORM is the automated persistence of objects in a Java application to the tables in a relational database.
Hibernate framework simplifies the development of java application to interact with the database. Hibernate is an open source, lightweight, ORM (Object Relational Mapping) tool.
An ORM solution consists of the following four components:
- API for performing basic CRUD operations
- API to express queries refering to classes
- Facilities to specify metadata
- Optimization facilities : dirty checking,lazy associations fetching
annotation that marks or clarifies the specific class as a Data Access Object.
annotation specifies that the class will be used as a component. This class cannot have a primary key of its own, it uses the enclosing class primary key.
annotate service layer level classes.
annotates presentation layer level classes.
JPA is the specification for an ORM framework whereas hibernate is the implmentation.
The ORM levels are,
- Pure relational (stored procedure.)
- Light objects mapping (JDBC)
- Medium object mapping
- Full object Mapping (composition,inheritance, polymorphism, persistence by reachability)
- Improved productivity
- High-level object-oriented API
- Less Java code to write
- No SQL to write
- Improved performance
- Sophisticated caching
- Lazy loading
- Eager loading
- Improved maintainability
- A lot less code to write
- Improved portability
- ORM framework generates database-specific SQL for you
The core interfaces of Hibernate framework are:
- Configuration
- SessionFactory
- Session
- Query
- Criteria
- Transaction
Yes, SessionFactory is a thread-safe object, many threads can access it simultaneously.
The application obtains Session instances from a SessionFactory. There is typically a single SessionFactory for the whole application created during application initialization. The SessionFactory caches generate SQL statements and other mapping metadata that Hibernate uses at runtime. It also holds cached data that has been read in one unit of work and may be reused in a future unit of work
SessionFactory sessionFactory = configuration.buildSessionFactory();
No, Session is not a thread-safe object, many threads can't access it simultaneously. In other words, you cannot share it between threads.
There are 3 states of object (instance) in hibernate.
- Transient: The object is in transient state if it is just created but has no primary key (identifier) and not associated with session.
- Persistent: The object is in persistent state if session is open, and you just saved the instance in the database or retrieved the instance from the database.
- Detached: The object is in detached state if session is closed. After detached state, object comes to persistent state if you call lock() or update() method.
If you mark a class as mutable="false", class will be treated as an immutable class. By default, it is mutable="true".
There are four types of association mapping in hibernate.
- One to One
- One to Many
- Many to One
- Many to Many
No, collection mapping can only be performed with One-to-Many and Many-to-Many.
Lazy loading in hibernate improves the performance. It loads the child objects on demand. Since Hibernate 3, lazy loading is enabled by default, you don't need to do lazy="true". It means not to load the child objects when parent is loaded.
Use update() if you are sure that the session does not contain an already persistent instance with the same identifier, and merge() if you want to merge your modifications at any time without consideration of the state of the session.
Using <generator> tag.
<id column="USER_ID" name="id" type="java.lang.Long"> <generator class="sequence"> <param name="table">SEQUENCE_NAME</param> <generator> </id>
- Bag
- Set
- List
- Array
- Map
The proxy attribute enables lazy initialization of persistent instances of the class. Hibernate will initially return CGLIB proxies which implement the named interface. The actual persistent object will be loaded when a method of the proxy is invoked.
Callback interfaces allow the application to receive a notification when something interesting happens to an object, for example, when an object is loaded, saved, or deleted. Hibernate applications don't need to implement these callbacks, but they're useful for implementing certain kinds of generic functionality.
There are three types of inheritance models in Hibernate:
- Table per class hierarchy
- Table per subclass
- Table per concrete class
- Hibernate is database independent while in case of JDBC, developer has to write database specific queries.
- In case of Hibernate developer doesn't need to be an expert of writing complex queries as HQL simplifies query writing process while in case of JDBC, its job of developer to write and tune queries. HQL is more object oriented and close to Java.
- In Hibernate, Criteria Query takes care of Query Tuning. In case of JDBC you need to tune your queries.
- No need to create any connection pool in case of Hibernate. You can use c3p0. In case of JDBC you need to write your own connection pool.
- Automatic primary key generation.
- Performance benefits like Lazy initialization, Outer join fetching, Batch fetching.
- Hibernate eliminates a lot of boiler plate code.
- Hibernate supports inheritance, associations, and collections.
- Hibernate implicitly provides transaction management.
- Hibernate wraps JDBCException that are unchecked so exception handling is NOT mandatory.
- Hibernate support cache memory.
This is the primary interface used by hibernate applications. The instances of this interface are lightweight and are inexpensive to create and destroy. Hibernate sessions are not thread safe.
This is a factory that delivers the session objects to hibernate application. Generally there will be a single SessionFactory for the whole application and it will be shared among all the application threads.
This interface is used to configure and bootstrap hibernate. The instance of this interface is used by the application in order to specify the location of hibernate specific mapping documents.
This is an optional interface but the above three interfaces are mandatory in each and every application. This interface abstracts the code from any kind of transaction implementations such as JDBC transaction, JTA transaction.
This interface allows the user to perform queries and also control the flow of the query execution.
These interfaces are used in the application to receive a notification when some object events occur. Like when an object is loaded, saved or deleted. There is no need to implement callbacks in hibernate applications, but they're useful for implementing certain kinds of generic functionality.
POJO stands for plain old java objects. These are just basic JavaBeans that have defined setter and getter methods for all the properties that are there in that bean. Besides they can also have some business logic related to that property.
The detached criteria allows you to create the query without Session. Then you can execute the search in an arbitrary session.
Using a DetachedCriteria is exactly the same as a Criteria except you can do the initial creation and setup of your query without having access to the session. When it comes time to run your query, you must convert it to an executable query with getExecutableCriteria(session).
DetachedCriteria query = DetachedCriteria.forClass(Person.class) .add( Property.forName("sex").eq('F') ); Transaction txn = session.beginTransaction(); List results = query.getExecutableCriteria(session).setMaxResults(100).list(); txn.commit(); session.close();
- useful to make join conditions, subselects, and to query outside the current session.
- code reuse
Hibernate ends up executing N+1 SQL queries to populate a collection of N elements referred as N+1 SELECT problem that occurs due to N+1 lazy loading and load on demand fetching strategy.
Let's say you have a collection of company objects (database rows), and each company has a collection of employee objects (database rows). In other words, company:employee is a 1-to-many relationship. If you need to iterate through all the companies, and for each one, print out a list of the employees, you have to perform one select to get all companies, and then N additional selects to find the list of employees, where N is the total number of companies.
Here are some of the strategies to solve the N+1 problem.
- pre-fetching in batches, this will reduce N+1 problem to N/K + 1 problem where K is size of batch.
- subselect fetching strategy.
- and disable lazy loading.
The important components in Hibernate architecture are,
- SessionFactory,
- Session,
- Persistent objects,
- and Transaction.
org.hibernate.SessionFactory : Refers to the cache of compiled mappings (hbm?s or annotation based) for a single database.
org.hibernate. Session : Represents a conversation between the java application and the persistent store. It is a wrapper around JDBC java.sql.Connection.
Persistent objects : JavaBeans/POJOs with the persistent state and business function associated with one org.hibernate.Session.
org.hibernate.Transaction used by Java application to specify atomic units of work. It abstracts the application from the underlying JDBC, JTA or CORBA transaction.
Setting the property show_sql to true at the hibernate configuration file enable viewing SQL on the console for debugging purposes.
<property name="show_sql">true</property>
Yes, a Hibernate Entity class can be declared final, however it is not a good practice.
Hibernate uses the proxy pattern for performance improvement during lazy association, by making an entity final, Hibernate will no longer be able to use a proxy as Java doesn't allow the final class to be extended.
In Hibernate, there are 3 approaches to call a database store procedure.
- Use createSQLQuery() to call a store procedure directly.
- Use @NamedNativeQueries annotation.
- Declare your store procedure inside the sql-query tag.
In hibernate framework, we have Transaction interface that defines the unit of work. It maintains abstraction from the transaction implementation (JTA,JDBC).
A transaction is associated with Session and instantiated by calling session.beginTransaction().
The transaction interfaces defines the below methods.
- void begin() starts a new transaction.
- void commit() ends the unit of work unless we are in FlushMode.NEVER.
- void rollback() forces this transaction to rollback.
- void setTimeout(int seconds) it sets a transaction timeout for any transaction started by a subsequent call to begin on this instance.
- boolean isAlive() checks if the transaction is still alive.
- void registerSynchronization(Synchronization s) registers a user synchronization callback for this transaction.
- boolean wasCommited() checks if the transaction is commited successfully.
- boolean wasRolledBack() checks if the transaction is rolledback successfully.
FetchType (Lazy/Eager) instructs whether the entity to be loaded eagerly or lazy, when there is a call.
FetchMode (Select/Join) instructs whether the entitity to be loaded with additional select or in one query with join or subselect.
If the Hibernate annotation @Fetch is not present on a field, then the default FetchMode for this field is decided based on the FetchType.
If the field has FetchType = EAGER, then FetchMode = JOIN. Otherwise, FetchMode = SELECT.
The EAGER strategy is a requirement on the persistence provider runtime that data must be eagerly fetched. The LAZY strategy is a hint to the persistence provider runtime that data should be fetched lazily when it is first accessed.
@ElementCollection maps non-entities (embeddable or basic) while @OneToMany is used to map entities.
Support of Java 8 in Hibernate 5 is one of the major changes and it supports Java 8 Date and Time API.
Hibernate 5 supports full-text search through Lucene 5.
Hibernate 5 through OGM provides the support for persistence to the NoSQL Databases such as MongoDB, REDIS.
@NamedQuery and other Hibernate annotations are now repeatable and can be assigned multiple times.This eliminates the use of container annotations such as @NamedQueries.
session.load() will throw an ObjectNotFoundException when no row found while session.get returns null.
Criteria. | HQL query |
Criteria query performs only SELECT operations. | HQL query performs both SELECT and NON-SELECT operations. HQL can be used to perform SELECT, INSERT, UPDATE, DELETE. |
Criteria supports pagination. | HQL doesn't support pagination. |
Criteria query is safe from SQL injection because of dynamic query generation. | HQL queries are either fixed or parametrized, SQL injection may happen if the developer doesn't parameterize properly. |