Hibernate API
JPA specification for all interfaces are present in
javax.persistance
and it sub-packages.
Introduction
org.hibernate.Session
is an interface.Session is associated implicitly with L1 cache (having same scope as the session lifetime), also referred to as Persistence context.
Methods for doing CRUD operations on a session are as follows,
MethodDescriptionsave()
Inserting the record
get()
/load()
Retrieving the record
update()
Updating the record
delete()
Deleting the record
public void delete(Object ref)
reference either persistent or detached pojo reference.
SessionFactory
It represents a provider factory of session objects. (provider/supplier of session objects).
We use instance of
org.hibernate.SessionFactory
to create session object (viaopenSession()
orgetCurrentSession()
).SessionFactory
is singleton (1 instance per DB/application), immutable, inherently thread safe.It is a heavy weight object, therefore it has to be created only once for an application at the very beginning of application life cycle.
org.hibernate.SessionFactory
has two apisgetCurrentSession
andopenSession()
.
openSession
getCurrentSession
opens NEW session from Session Factory, which has to be explicitly closed by programmer.
Opens new session, if one doesn't exist, otherwise continues with the exisitng one.
Have to close explicitly
Gets automatically closed upon Transaction boundary or thread over (since current session is bound to current thread) mentioned in hibernate.cfg.xml
property (current_session_context_class thread)
Configuration
Comes under
org.hibernate.cfg.Configuration
package, used before hibernate4.x.
Configuration object is used to create the SessionFactory object.
Object Oriented Representation of Hibernate configuration file and mapping file is nothing but Configuration object.
When we call
configure()
method on configuration object, hibernate configuration file (hibernate.cfg.xml placed in run time classpath) and mapping files are loaded in the memory.
Entity Life cycle
Transient State
An object is said to be in transient state, if it is not associated with the session, and has no matching record in the database table.
Persistent State
An object is said to be in persistent state, if it is associated with session object (L1 cache) and will result into a matching record in the database table upon commit.
Note
When the POJO is in persistent state it will be in synchronization with the matching record in database i.e if we make any changes to the state of the persistent POJO it will be reflected in the database only after commiting transaction _ i.e automatic dirty checking will be performed (resulting in to insert/update/delete).
Detached state
Object is not associated with session but has matching record in the database table.
If we make any changes to the state of detached object it will not be reflected in the database.
Following methods are used to make a persistent object, detached.
Note :
By calling
update()
method on session object it will go from detached state to persistent state.By calling
delete()
method on session object it will go from persistent state to transient state.
State Transition Diagram
Session API
Persists specified transient POJO on underlying DB, upon committing the transaction.
In comparison to
save()
, this method does not return the generated identifier.
I/P transient POJO reference
save()
method auto persists transient POJO in the DB upon committing transaction & returns unique serializable ID generated by hibernate framework, if@GeneratedValue
is used for Id.
For data retrieval by Primary Key i.e Id
Returns null, if id is not found
Returns PERSISTENT pojo reference if id is found.
Usage of Hibernate Session API's
get()
,
When
clear()
is called on session object all the objects associated with the session object become detached.Note that the databse connection is not closed. (Completely clears the session. Evicts all loaded instances and cancel all pending saves, updates and deletions).
When
close()
is called on session object all the objects associated with the session object become detached and also closes the database connection.
It detaches a particular persistent object or disassociates from the session. (Remove this instance from the session cache. Changes to the instance will not be synchronized with the database).
When the object is in persistent state, whatever changes we made to the object state will be reflected in the database only at the end of transaction.
If we want to reflect the changes before the end of transaction (i.e before commiting the transaction) call the flush method. (Flushing is the process of synchronizing the underlying DB state with persistable state of session cache).
Whether the transaction will be committed on flush depends on
org.hibernate.FlushMode
value.
The method indicates whether the object is associated with session or not.
This method is used to get the latest data from database and make corresponding modifications to the persistent object state. (Re-read the state of the given instance from the underlying database).
If object is in persistent state no need of calling the update method.
As the object is in sync with the database, whatever changes made to the object will be reflected to database at the end of transaction.
When the object is in detached state, record is present in the table but object is not in sync with database, therefore
update()
method can be called to update the record in the table.Which exceptions update method can raise?
StaleStateException
If you are trying to update a record (using
session.update(ref)
), whose id doesn't exist, i.e update can't transition from transient to persistent state.It can only transition from detached to persistent.
NonUniqueObjectException
If there is already persistence instance with same id in session.
Can Transition from transient, persistent & detached to persistent. Regarding Hibernate merge,
The state of a transient or detached instance may also be made persistent as a new persistent instance by calling merge().
Copies the state of the given object (can be passed as transient or detached) onto the persistent object with the same identifier.
If there is no persistent instance currently associated with the session, it will be loaded. Return the persistent instance.
If the given instance is unsaved, save a copy of it and return it as a newly persistent instance. The given instance does not become associated with the session.
It will not throw
NonUniqueObjectException
, even if there is already persistence instance with same id in session.
The method persists the object (insert) if matching record is not found with id initialized to default value or fires update query.
If you supply Object, with non-existing ID throws
StaleStateException
.This method is different from merge because, for this method the reference should be part of persistence context.
When
lock()
method is called on the session object for a persistent object, untill the transaction is commited in the hibernate application. Externally the matching record in the table cannot be modified.
POJO is marked for removal, corresponding row from DB will be deleted after comitting transaction & closing of session.
One can use directly "delete HQL" & perform deletions, for eg,
Some interesting API behavior and differences
Differences
Difference in
get()
&load()
get(...)load(...)If id doesn't exist it returns null.
If id doesn't exist & you are accessing it from within hibernate session it throws ObjectNotFoundException.
Hibernate uses eager fetching policy, meaning it will generate select query always & load the state from DB in persistent POJO reference. So, even if you access the same from within the session(persistent pojo) or outside (detached) the hibernate session throws NO EXCEPTION(proxy + state).
Hibernate uses lazy fetching policy, meaning it will, by default NOT generate any select query, so what you have is ONLY PROXY (i.e., wrapper with no state loaded from DB). On such a proxy if you access anything outside the hibernate session (i.e in detached state) one will get
LazyInitializationException
How to fix this? 1. Change fetch type to eager (NOT AT ALL recommended) as this will lead to no caching, hence disabling L1 cache) 2. If you want to access any POJO in detached manner (i.e outside hibernate session scope) fire non-id get method from within session & then hibernate has to load entire state from DB hence NOLazyInitializationException
Lazy fetching becomes important in relationships or in
load()
v/sget()
.When a client requests an entity (eg - Course POJO) and its associated graph of objects (eg -Student POJO) from the database, it isn't usually necessary to retrieve the whole graph of every (indirectly) associated object.
You wouldn't want to load the whole database into memory at once. For example, loading a single Category shouldn't trigger the loading of all Items in that category (one to many relationship).
update()
v/smerge()
Both methods transition detached object to persistent state.
UpdateMergeIf you are sure that the session does not contain an already persistent instance with the same identifier then use update to save the data in hibernate. If session has an object with same id , then it throws
org.hibernate.NonUniqueObjectException
because a different object with the same identifier value was already been associated with the session.If you want to save your modifications at any time with out knowing about the state of an session then use
merge()
in hibernate.
persist()
v/ssave()
public void persist(Object transientRef)
If you set id (primary key) before calling
persist(ref)
, thatId
may be existing or not existing in the persistence store, this api gives exceptionorg.hibernate.PersistentObjectException
with the following error messagedetached entity passed to persist
. This is because when you set an Id, effectively you make it detached. Hence, the error.public Serializable save(Object ref)
if you set some non-null id (primary key) which may be existing or non-existing, while calling
save(ref)
this api doesn't give any exception. It ignores your passed id & creates its own id & inserts a row.
Interesting Behaviors
public void saveOrUpdate(Object ref)
Either inserts/updates or throws exception
null id, fires insert (works as save)
non-null id, but existing id, fires update (works as update)
non-null id, but non existing id in persistent context i.e detached, then it throws
StaleStateException
, to indicate that we are trying to delete or update a row that does not exist.
public Object merge(Object ref)
Instance to be merged must be either transient or detached POJO reference
It returns persistent pojo reference.
null id, fires insert (works as save)
non-null but existing id, fires update (select , update).
non-null but non existing id, no exception is thrown. It just ignores the passed id & creates its own id & inserts a row (select,insert).
public void update(Object object)
Update the persistent instance with the identifier of the given detached instance.
Input argument object should be detached pojo containing updated state.
Detached pojo becomes persistent after this operation.
Exception associated :
Throws
org.hibernate.TransientObjectException
, when given object has a null identifier. When calling update if you give null id. It fails as input object is not in detached state. (transient ----X---> persistent via update).Throws
org.hibernate.StaleStateException
to indicate that we are trying to delete or update a row that does not exist.org.hibernate.NonUniqueObjectException
a different object with the same identifier value was already associated with the session.
Last updated