Hibernate is
an open source Java persistence framework project.
It performs powerful object-relational mapping and query databases using HQL
and SQL. Hibernate is a great tool for ORM mappings in
Java. It can cut down a lot of complexity and thus defects as well from your
application, which may otherwise find a way to exist.
Initially started as an ORM
framework, Hibernate has spun off into many projects, such as Hibernate
Search, Hibernate Validator, Hibernate OGM (for
NoSQL databases), and so on.
Hibernate Architecture
Let’s understand what each
block represents.
1. Configuration:
Generally written in
hibernate.properties
or hibernate.cfg.xml
files(for
xml based). For Java configuration, you may find class annotated with @Configuration
. It
is used by Session Factory to work with Java Application and the Database. It
represents an entire set of mappings of an application Java Types to an SQL
database.
2. Session Factory: Any
user application requests Session Factory for a session object. Session Factory
uses configuration information from above listed files or from @Configuration
java file, to instantiates the session object appropriately.
3. Session: This
represents the interaction between the application and the database at any
point of time. This is represented by the
org.hibernate.Session
class.
The instance of a session can be retrieved from the SessionFactory
bean.
4. Query: It
allows applications to query the database for one or more stored objects.
Hibernate provides different techniques to query database, including
NamedQuery
and Criteria API
.
5. First-level cache: It
represents the default cache used by Hibernate Session object while interacting
with the database. It is also called as session cache and caches objects within
the current session. All requests from the Session object to the database must
pass through the first-level cache or session cache. One must note that the
first-level cache is available with the session object until the Session object
is live.
6. Transaction:
enables you to achieve data consistency, and rollback in case something goes
unexpected.
7. Persistent objects:
These are plain old Java objects (POJOs), which get persisted as one of the
rows in the related table in the database by hibernate. They can be configured
in configurations files (
hibernate.cfg.xml
or hibernate.properties
) or
annotated with @Entity
annotation.
8. Second-level cache: It
is used to store objects across sessions. This needs to be explicitly enabled
and one would be required to provide the cache provider for a second-level
cache. One of the common second-level cache providers is EhCache.
Salient features of the Hibernate
framework
·
Object/Relational Mapping
Hibernate, as an ORM
framework, allows the mapping of the Java domain object with database tables
and vice versa. As a result, business logic is able to access and manipulate database
entities via Java objects. It helps to speed up the overall development process
by taking care of aspects such as transaction management, automatic primary key
generation, managing database connections and related implementations, and so
on.
·
JPA provider
Hibernate does support
the Java Persistence API (JPA) specification.
JPA is a set of specifications for accessing, persisting, and managing data
between Java objects and relational database entities.
·
Idiomatic persistence
Any class that follows object-oriented principles such as inheritance, polymorphism, and so on, can be
used as a persistent class.
·
High performance and scalability
Hibernate supports
techniques such as different fetching strategies, lazy initialization,
optimistic locking, and so on, to achieve high performance, and it scales well
in any environment.
·
Easy to maintain
Hibernate is easier to
maintain as it requires no special database tables or fields. It generates SQL
at system initialization time. It is much quicker and easier to maintain
compared to JDBC.
Hibernate
Properties
Following
is the list of important properties, you will be required to configure for a
databases in a standalone situation
Sr.No.
|
Properties &
Description
|
1
|
hibernate.dialect
This property makes Hibernate generate the appropriate
SQL for the chosen database.
|
2
|
hibernate.connection.driver_class
The JDBC driver class.
|
3
|
hibernate.connection.url
The JDBC URL to the database instance.
|
4
|
hibernate.connection.username
The database username.
|
5
|
hibernate.connection.password
The database password.
|
6
|
hibernate.connection.pool_size
Limits the number of connections waiting in the Hibernate
database connection pool.
|
7
|
hibernate.connection.autocommit
Allows auto commit mode to be used for the JDBC
connection.
|
If you are using a database along with an application
server and JNDI, then you would have to configure the following properties −
Sr.No.
|
Properties & Description
|
1
|
hibernate.connection.datasource
The JNDI name defined
in the application server context, which you are using for the application.
|
2
|
hibernate.jndi.class
The Initial Context
class for JNDI.
|
3
|
hibernate.jndi.<JNDIpropertyname>
Passes any JNDI
property you like to the JNDI InitialContext.
|
4
|
hibernate.jndi.url
Provides the URL for
JNDI.
|
5
|
hibernate.connection.username
The database username.
|
6
|
hibernate.connection.password
The database password.
|
Hibernate - Sessions
A Session is used to get a
physical connection with a database. The Session object is lightweight and
designed to be instantiated each time an interaction is needed with the
database. Persistent objects are saved and retrieved through a Session object.
The session objects should not be kept open for a long time
because they are not usually thread safe and they should be created and
destroyed them as needed. The main function of the Session is to offer, create,
read, and delete operations for instances of mapped entity classes.
Instances may exist in one of the following three states at a
given point in time −
· transient − A
new instance of a persistent class, which is not associated with a Session and
has no representation in the database and no identifier value is considered
transient by Hibernate.
· persistent −
You can make a transient instance persistent by associating it with a Session.
A persistent instance has a representation in the database, an identifier value
and is associated with a Session.
· detached −
Once we close the Hibernate Session, the persistent instance will become a
detached instance.
Association Mappings
The
mapping of associations between entity classes and the relationships between
tables is the soul of ORM.
Sr.No.
|
Mapping type &
Description
|
1
|
Mapping many-to-one relationship using Hibernate
|
2
|
Mapping one-to-one relationship using Hibernate
|
3
|
Mapping one-to-many relationship using Hibernate
|
4
|
Mapping many-to-many relationship using Hibernate
|
Hibernate - Annotations
import javax.persistence.*;
@Entity
@Table(name = "EMPLOYEE")
public class Employee {
@Id @GeneratedValue
@Column(name = "id")
private int id;
@Column(name = "first_name")
private String firstName;
@Column(name = "last_name")
private String lastName;
@Column(name = "salary")
private int salary;
public Employee() {}
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 getSalary() {
return salary;
}
public void setSalary( int salary ) {
this.salary = salary;
}
}
@Entity Annotation
@Entity annotation to the Employee class, which marks this
class as an entity bean, so it must have a no-argument constructor that is
visible with at least protected scope.
@Table Annotation
The
@Table annotation allows you to specify the details of the table that will be
used to persist the entity in the database.
The
@Table annotation provides four attributes, allowing you to override the name
of the table, its catalogue, and its schema, and enforce unique constraints on
columns in the table.
@Id and @GeneratedValue Annotations
Each
entity bean will have a primary key, which you annotate on the class with
the @Id annotation. The primary key can be a single field or a
combination of multiple fields depending on your table structure.
By
default, the @Id annotation will automatically determine the most appropriate
primary key generation strategy to be used but you can override this by
applying the @GeneratedValue annotation, which takes two
parameters strategy and generator.
@Column Annotation
The
@Column annotation is used to specify the details of the column to which a
field or property will be mapped. You can use column annotation with the
following most commonly used attributes −
· name attribute
permits the name of the column to be explicitly specified.
· length attribute
permits the size of the column used to map a value particularly for a String
value.
· nullable attribute
permits the column to be marked NOT NULL when the schema is generated.
· unique attribute
permits the column to be marked as containing only unique values.
Generator classes in Hibernate
The <generator> class
is a sub-element of id. It is used to generate the unique identifier for the
objects of persistent class. There are many generator classes defined in the
Hibernate Framework. Some of them are listed below.
1) assigned
It is the default generator strategy if there is no
<generator> element. In this case, application assigns the id
2) increment
It generates the unique id only if no other process is
inserting data into this table. It generates. If a table contains an identifier
then the application considers its maximum value else the application consider
that the first generated identifier is 1. For each attribute value, hibernate
increment the identifier by 1.
3) sequence
It uses the sequence of the database. if there is no sequence defined, it
creates a sequence automatically e.g. in case of Oracle database, it creates a
sequence named HIBERNATE_SEQUENCE. And
many more….
Hibernate -
Caching
Caching
is a mechanism to enhance the performance of a system. It is a buffer memory that
lies between the application and the database. Cache memory stores recently
used data items in order to reduce the number of database hits as much as
possible.
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.
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.
|
The following compatibility matrix will help you
choose an appropriate combination.
Strategy/Provider
|
Read-only
|
Nonstrictread-write
|
Read-write
|
Transactional
|
EHCache
|
X
|
X
|
X
|
|
OSCache
|
X
|
X
|
X
|
|
SwarmCache
|
X
|
X
|
|
|
JBoss Cache
|
X
|
|
|
X
|
Concurrency
Strategies
A
concurrency strategy is a mediator, which is responsible for storing items of
data in the cache and retrieving them from the cache. If you are going to
enable a second-level cache, you will have to decide, for each persistent class
and collection, which cache concurrency strategy to use.
· Transactional −
Use this strategy for read-mostly data where it is critical to prevent stale
data in concurrent transactions, in the rare case of an update.
· Read-write −
Again use this strategy for read-mostly data where it is critical to prevent
stale data in concurrent transactions, in the rare case of an update.
· Nonstrict-read-write −
This strategy makes no guarantee of consistency between the cache and the
database. Use this strategy if data hardly ever changes and a small likelihood
of stale data is not of critical concern.
· Read-only − A
concurrency strategy suitable for data, which never changes. Use it for reference
data only.
SpringBoot-Hibernate-Transactions
Spring Hibernate
Transactions example
Ways of Managing Transactions
A transaction can be
managed in the following ways:
1. Programmatically manage by writing custom
code
This is the legacy way
of managing transaction.
EntityManagerFactory factory =
Persistence.createEntityManagerFactory("PERSISTENCE_UNIT_NAME");
EntityManager entityManager = entityManagerFactory.createEntityManager();
Transaction transaction = entityManager.getTransaction()
try
{
transaction.begin();
someBusinessCode();
transaction.commit();
}
catch(Exception ex)
{
transaction.rollback();
throw ex;
}
EntityManager entityManager = entityManagerFactory.createEntityManager();
Transaction transaction = entityManager.getTransaction()
try
{
transaction.begin();
someBusinessCode();
transaction.commit();
}
catch(Exception ex)
{
transaction.rollback();
throw ex;
}
Pros:
The scope of the
transaction is very clear in the code.
Cons:
It's repetitive and
error-prone. Any error can have a very high impact. A lot of boilerplate needs
to be written and if you want to call another method from this method then
again you need to manage it in the code.
2. Use Spring to manage the transaction
Spring supports two
types of transaction management:
1. Programmatic
transaction management: This
means that you have to manage the transaction with the help of programming.
That gives you extreme flexibility, but it is difficult to maintain.
2. Declarative transaction management: This means you separate transaction management from the business code. You only use annotations or XML-based configuration to manage the transactions.
2. Declarative transaction management: This means you separate transaction management from the business code. You only use annotations or XML-based configuration to manage the transactions.
Choosing between Programmatic and Declarative
Transaction Management:
- Programmatic transaction
management is good only if you have a small number of transactional
operations. (This is not a good best practice)
- Transaction name can be
explicitly set only using Programmatic transaction management.
- Programmatic transaction
management should be used when you want explicit control over managing
transactions.
- On the other hand, if your
application has numerous transactional operations, declarative transaction
management is worthwhile.
- Declarative Transaction
management keeps transaction management out of business logic, and is not
difficult to configure.
2.1 Programmatic
transaction management
The Spring Framework
provides two means of programmatic transaction management.
a. Using the
TransactionTemplate (Recommended by Spring Team)
b. Using a PlatformTransactionManager
implementation directly
2.2. Declarative
Transaction Step 1: Define
a transaction manager in your spring application
@Autowired
@Bean(name = "transactionManager")
public HibernateTransactionManager getTransactionManager(SessionFactory sessionFactory) {
HibernateTransactionManager transactionManager = new HibernateTransactionManager(sessionFactory);
return transacationManager;
}
@Bean(name = "transactionManager")
public HibernateTransactionManager getTransactionManager(SessionFactory sessionFactory) {
HibernateTransactionManager transactionManager = new HibernateTransactionManager(sessionFactory);
return transacationManager;
}
Step 2: Turn on support for transaction
annotations by adding below entry to your spring application @EnableTransactionManagement public
class AppConfig { ... }
Step 3: Add the @Transactional annotation to the Class (or method in a class) or
Interface (or method in an interface).
- The @Transactional annotation
may be placed before an interface definition, a method on an interface, a
class definition, or a public method on a class.
- If you want some methods in the
class (annotated with @Transactional) to have different attributes
settings like isolation or propagation level then put annotation at method
level which will override class level attribute settings.
@Transactional attributes.
@Transactional
(isolation=Isolation.READ_COMMITTED)
The default is
Isolation.DEFAULT Most of the times, you will use default unless and until you
have specific requirements. Informs the transaction (tx) manager that the
following isolation level should be used for the current tx. Should be set at
the point from where the tx starts because we cannot change the isolation level
after starting a tx. DEFAULT: Use the default isolation level
of the underlying database.
READ_COMMITTED: A constant indicating that dirty reads
are prevented; non-repeatable reads and phantom reads can occur.
READ_UNCOMMITTED: This isolation level states that a
transaction may read data that is still uncommitted by other transactions.
REPEATABLE_READ: A constant indicating that dirty reads
and non-repeatable reads are prevented; phantom reads can occur.
SERIALIZABLE: A constant indicating that dirty reads,
non-repeatable reads, and phantom reads are prevented.
What do these Jargons
dirty reads, phantom reads, or repeatable reads mean?
Dirty Reads: Transaction "A" writes a
record. Meanwhile, Transaction "B" reads that same record before
Transaction A commits. Later, Transaction A decides to rollback and now we have
changes in Transaction B that are inconsistent. This is a dirty read.
Transaction B was running in READ_UNCOMMITTED isolation level so it was able to
read Transaction A changes before a commit occurred.
Non-Repeatable Reads: Transaction "A" reads some
record. Then Transaction "B" writes that same record and commits.
Later Transaction A reads that same record again and may get different values
because Transaction B made changes to that record and committed. This is a
non-repeatable read.
Phantom Reads: Transaction "A" reads a range
of records. Meanwhile, Transaction "B" inserts a new record in the
same range that Transaction A initially fetched and commits. Later Transaction
A reads the same range again and will also get the record that Transaction B
just inserted. This is a phantom read: a transaction fetched a range of
records multiple times from the database and obtained different result sets
(containing phantom records).
@Transactional(propagation=Propagation.REQUIRED)
If not specified, the default
propagational behavior is REQUIRED.
Other options are
REQUIRES_NEW , MANDATORY , SUPPORTS , NOT_SUPPORTED , NEVER , and NESTED .
REQUIRED
Indicates that the target method cannot run without an active tx. If a tx has already been started before the invocation of this method, then it will continue in the same tx or a new tx would begin soon as this method is called.
Indicates that the target method cannot run without an active tx. If a tx has already been started before the invocation of this method, then it will continue in the same tx or a new tx would begin soon as this method is called.
REQUIRES_NEW
Indicates that a new tx has to start every time the target method is called. If already a tx is going on, it will be suspended before starting a new one.
Indicates that a new tx has to start every time the target method is called. If already a tx is going on, it will be suspended before starting a new one.
MANDATORY
Indicates that the target method requires an active tx to be running. If a tx is not going on, it will fail by throwing an exception.
Indicates that the target method requires an active tx to be running. If a tx is not going on, it will fail by throwing an exception.
SUPPORTS
Indicates that the target method can execute irrespective of a tx. If a tx is running, it will participate in the same tx. If executed without a tx it will still execute if no errors. Methods which fetch data are the best candidates for this option.
Indicates that the target method can execute irrespective of a tx. If a tx is running, it will participate in the same tx. If executed without a tx it will still execute if no errors. Methods which fetch data are the best candidates for this option.
NOT_SUPPORTED
Indicates that the target method doesn’t require the transaction context to be propagated. Mostly those methods which run in a transaction but perform in-memory operations are the best candidates for this option.
Indicates that the target method doesn’t require the transaction context to be propagated. Mostly those methods which run in a transaction but perform in-memory operations are the best candidates for this option.
NEVER
Indicates that the target method will raise an exception if executed in a transactional process. This option is mostly not used in projects.
Indicates that the target method will raise an exception if executed in a transactional process. This option is mostly not used in projects.
@Transactional
(rollbackFor=Exception.class)
- Default is
rollbackFor=RunTimeException.class
- In Spring, all API classes
throw RuntimeException, which means if any method fails, the container
will always rollback the ongoing transaction.
- The problem is only with
checked exceptions. So this option can be used to declaratively rollback a
transaction if Checked Exception occurs.
@Transactional
(noRollbackFor=IllegalStateException.class)
Indicates that a
rollback should not be issued if the target method raises this exception.
@Transactional(timeout=60)
Defaults to the
default timeout of the underlying transaction system.
Informs the tx manager
about the time duration to wait for an idle tx before a decision is taken to
rollback non-responsive transactions.
@Transactional:
Service or DAO Layer?
The Service is the
best place for putting @Transactional, service layer should hold the
detail-level use case behavior for a user interaction that would logically go
in a transaction.
There are a lot of
CRUD applications that don't have any significant business logic for them
having a service layer that just passes data through between the controllers
and data access objects is not useful. In these cases we can put transaction annotation
on Dao.
So in practice you can
put them in either place, it's up to you.
Also if you put
@Transactional in DAO layer and if your DAO layer is getting reused by
different services then it will be difficult to put it on DAO layer as
different services may have different requirements.
If your service layer
is retrieving objects using Hibernate and let's say you have lazy
initializations in your domain object definition then you need to have a
transaction open in service layer else you will face LazyInitializationException
thrown by the ORM.
This blog is so nice to me. I will keep on coming here again and again. Visit my link as well.
ReplyDeleteHibernate Training in Chennai
Spring and Hibernate Training
Hibernate Training in Anna Nagar
Spring Training in Chennai
Spring course in Chennai
soft skills training in chennai
core java training in chennai
Hibernate Training in T Nagar