You are on page 1of 37

Object/relational mapping

Object/relational mapping is the automated (and transparent) persistence of objects in a Java application to the
tables in a relational database, using metadata that describes the mapping between the objects and the database.

What are the benefits of ORM and Hibernate?


The main advantage of ORM like hibernate is that it shields developers from messy SQL. Apart from this, ORM
provides following benefits:
Productivity
a. High-level object-oriented API
b. Less Java code to write
c. No SQL to write
Performance
a. Sophisticated caching
b. Lazy loading
c. Eager loading
Maintainability
a. A lot less code to write
Portability
a. ORM framework generates database-specific SQL for you

An ORM solution consists of the followig four pieces:


1. API for performing basic CRUD operations
2. API to express queries refering to classes
3. Facilities to specify metadata
4. Optimization facilities : dirty checking,lazy associations fetching

Hibernate simplifies:
 Saving and retrieving your domain objects
 Making database column and table name changes
 Centralizing pre save and post retrieve logic
 Complex joins for retrieving related items
 Schema creation from object model
JPA:
JPA is a specification for Object Relational Mapping. It does not have any implementation and it specifies set of
guidelines for JPA implementations or vendors.
There are multiple JPA providers
1) Hibernate
2) Open JPA
3) Eclipse Link
Most popular among these is Hibernate. Actually Hibernate started as a ORM framework much before the JPA
inception. Starting from Release 3.2 Hibernate provided implementation for JPA. Hibernate provides extra features in
addition to JPA specification. We can think of Hibernate as a super set of JPA and JPA as sub set of Hibernate.
Hibernate features not yet supported by JPA
1) Wide identifier generator features.
2) More flush modes
3) Exclude fields from optimistic locking
4) Support for Java 8 Date and Time.
5) Versionless optimistic locking.
Page 1 of 37
Architecture:

The core interfaces

The five core interfaces are used in just about every Hibernate application.

Session interface
1. The Hibernate notion of a session is something between connection and transaction.
2. It may be easier to think of a session as a cache or collection of loaded objects relating to a single unit of work.
Hibernate can detect changes to the objects in this unit of work.
3. We sometimes call the Session a persistence manager because it’s also the interface for persistence-related
operations such as storing and retrieving objects.
4. An instance of Session is lightweight and is inexpensive to create and destroy.
5. Hibernate sessions are not thread-safe and should by design be used by only one thread at a time.

Session-Factory interface
1. The application obtains Session instances from a Session-Factory. The Session-Factory is certainly not
lightweight! It’s intended to be shared among many application threads. There is typically a single Session-
Factory for the whole application—created during application initialization, for example. However, if your
application accesses multiple databases using Hibernate, you’ll need a Session-Factory for each database.
2. The Session-Factory caches generated 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 (only if class and collection mappings specify that this second-level cache is desirable).

Configuration interface

1. The Configuration object is used to configure and bootstrap Hibernate.

Page 2 of 37
2. The application uses a Configuration instance to specify the location of mapping documents and Hibernate-
specific properties and then create the Session-Factory.

Transaction interface

1. Hibernate applications may choose not to use this interface, instead managing transactions in their own
infrastructure code.
2. A Transaction abstracts application code from the underlying transaction implementation—which might be a
JDBC transaction, a JTA User-Transaction, or even a Common Object Request Broker Architecture (CORBA)
transaction— allowing the application to control transaction boundaries via a consistent API.

Query and Criteria interfaces

1. The Query interface allows you to perform queries against the database and control how the query is executed.
Queries are written in HQL or in the native SQL dialect of your database.
2. A Query instance is used to bind query parameters, limit the number of results returned by the query, and
finally to execute the query.
3. The Criteria interface is very similar; it allows you to create and execute object oriented criteria queries.
4. A Query instance is lightweight and can’t be used outside the Session that created it.
 Criteria queries are ideal for dynamic queries. It makes the task of adding ordering, leaving some parts (e.g.
restrictions) out depending on some parameter.
 HQL is ideal for static and complex queries coz it it’s much easier to read/understand HQL. It’s a bit more
powerful for join queries.
 There is a difference in terms of performance between HQL and criteriaQuery, everytime you fire a query using
criteriaQuery, it creates a new alias for the table name which does not reflect in the last queried cache for any DB.
This leads to an overhead of compiling the generated SQL, taking more time to execute.

Basic configuration:
Managed environment
a. A J2EE application server such as JBoss, BEA WebLogic, or IBM WebSphere implements the
standard (J2EE-specific) managed environment
b. Pools resources such as database connections and allows transaction boundaries and security to be
specified declaratively (that is, in metadata).
c. In managed environments, Hibernate integrates with container-managed transactions and datasources.
Non-managed environment
a. A servlet container like Jetty or Tomcat provides a nonmanaged server environment for Java web
applications. A stand-alone desktop or command-line application is also considered non-managed.
Nonmanaged environments don’t provide automatic transaction or resource management or security
infrastructure. The application itself manages database connections and demarcates transaction
boundaries.
b. In the case of a non-managed environment, Hibernate handles transactions and JDBC connections.
Hibernate can be configured for deployment in both environments.

Configuration in non-managed environments:


In a non-managed environment, such as a servlet container, hibernate is responsible for obtaining JDBC connections.
Generally, it isn’t advisable to create a connection each time you want to interact with the database. Instead, Java
applications should use a pool of JDBC connections.
There are three reasons for using a pool:
Page 3 of 37
 Acquiring a new connection is expensive.
 Maintaining many idle connections is expensive.
 Creating prepared statements is also expensive for some drivers.
Since this non-managed environment doesn’t implement connection pooling, the application must implement its own
pooling algorithm or rely upon a third-party library such as the open source C3P0 connection pool.
Without Hibernate, the application code usually calls the connection pool to obtain JDBC connections and execute
SQL statements.

Non-Managed Environment
Hibernate

Session
Application

JSP Transaction Connection Database


Pool
Servlet
Query

Hibernate with a connection pool in a non-managed environment


hibernate.connection.driver_class = org.postgresql.Driver The name of the Java class implementing the JDBC
Driver (the driver JAR file must be placed in the
application’s classpath).
hibernate.connection.url = jdbc:postgresql://localhost/auctiondb A JDBC URL that specifies the host and database
name for JDBC connections.

hibernate.connection.username = auctionuser The database user name.

hibernate.connection.password = secret The database password for the specified user.

hibernate.dialect = net.sf.hibernate.dialect.PostgreSQLDialect A Dialect for the database. Despite the ANSI


standardization effort, SQL is implemented differently
by various databases vendors. So, you must specify
a Dialect. Hibernate includes built-in support for all
popular SQL databases, and new dialects may be
defined easily.

hibernate.c3p0.min_size=5 The minimum number of JDBC connections that


C3P0 will keep ready.

hibernate.c3p0.max_size=20 The maximum number of connections in the pool. An


exception will be thrown at runtime if this number is
exhausted.

hibernate.c3p0.timeout=300 The timeout period (in this case, 5 minutes or 300


seconds) after which an idle connection will be
removed from the pool.

hibernate.c3p0.max_statements=50 The maximum number of prepared statements that


will be cached. Caching of prepared statements is
essential for best performance with Hibernate.

Page 4 of 37
hibernate.c3p0.idle_test_period=3000 The idle time in seconds before a connection is
automatically validated.

You declared the properties in a file named hibernate.properties, so you need only place this file in the application
classpath. It will be automatically detected and read when Hibernate is first initialized when you create a Configuration
object.

With Hibernate, hibernate acts as a client of the JDBC connection pool. The application code uses the Hibernate
Session and Query APIs for persistence operations and only has to manage database transactions, ideally using the
Hibernate Transaction API.

Let’s summarize the configuration steps:


1 .Download and unpack the JDBC driver for your database, which is usually available from the database
vendor web site. Place the JAR files in the application classpath; do the same with hibernate2.jar.
2. Add Hibernate dependencies to the classpath; they’re distributed along with Hibernate in the lib/ directory.
See also the text file lib/README.txt for a list of required and optional libraries.
3 .Choose a JDBC connection pool supported by Hibernate and configure it with a properties file. Don’t forget
to specify the SQL dialect.
4. Let the Configuration know about these properties by placing them in a hibernate.properties file in the
classpath.
5. Create an instance of Configuration in your application and load the XML mapping files using either
addResource() or addClass(). Build a Session- Factory from the Configuration by calling
buildSessionFactory().

SessionFactory sessionFactory = new Configuration()


.addResource("hello/Message.hbm.xml")
.setProperties( System.getProperties() )
.buildSessionFactory();

Configuration in managed environments:

A managed environment handles certain cross-cutting concerns, such as application security (authorization and
authentication), connection pooling, and transaction management. J2EE application servers are typical managed
environments.
Although application servers are generally designed to support EJBs, you can still take advantage of the other managed
services provided, even if you don’t use EJB entity beans.

EJBs call the same Hibernate APIs as servlets, JSPs, or stand-alone applications: Session, Transaction, and Query. The
Hibernate-related code is fully portable between non-managed and managed environments.
Hibernate handles the different connection and transaction strategies transparently.

Hibernate
Application Server

Application Session Transaction


Manager

EJB Transaction
Database Page 5 of 37
Resource
Manager
Query

Hibernate in a managed environment with an application server

 Java already has a standard transaction API, JTA, which is used to control transactions in a
managed environment with J2EE. This is called container-managed transactions(CMT).
 If a JTA transaction manager is present, JDBC connections are enlisted with this manager and
under its full control. This isn’t the case in a nonmanaged environment, where an application (or
the pool) manages the JDBC connections and JDBC transactions directly.

Managed and Non-managed environments can use different transaction methods. Since Hibernate needs to be
portable across these environments.The Hibernate Transaction interface abstracts the underlying JTA or JDBC
transaction (or, potentially, even a CORBA
transaction).

This underlying transaction strategy is set with the property hibernate. connection.factory_class, and it can take one of
the following two values:
a. net.sf.hibernate.transaction.JDBCTransactionFactory delegates to direct JDBC transactions. This
strategy should be used with a connection pool in a non-managed environment and is the default if no
strategy is specified.
b. net.sf.hibernate.transaction.JTATransactionFactory delegates to JTA.This is the correct strategy for
CMT, where connections are enlisted with JTA.

One of these features may be used with Hibernate:


Tomcat uses the DBCP connection pool internally but exposes it as a JNDI datasource, just like a
real application server. To configure the Tomcat datasource, you’ll need to edit server.xml according to
instructions in the Tomcat JNDI/JDBC documentation. You can configure Hibernate to use this
datasource by setting hibernate.connection. datasource. Keep in mind that Tomcat doesn’t ship with a
transaction manager.

Configuration can be mentioned in properties or xml file


Using XML based configuration:

?xml version='1.0'encoding='utf-8'?>
<!DOCTYPE hibernate-configuration PUBLIC "-//Hibernate/Hibernate Configuration DTD//EN"
"http://hibernate.sourceforge.net/hibernate-configuration-3.0.dtd">
<hibernate-configuration>
<session-factory name="java:/hibernate/HibernateFactory">
<property name="show_sql">true</property>
<property name="connection.datasource">java:/comp/env/jdbc/AuctionDB</property>
<property name="dialect">org.hibernate.dialect.Oracle10gDialect</property>
<property
name="transaction.manager_lookup_class">org.hibernate.transaction.JBossTransactionManagerLookup<
/property>
<property name="hibernate.dialect" value="org.hibernate.dialect.Oracle10gDialect"/>

Page 6 of 37
<property name="hibernate.ejb.interceptor"
value="com.comp.core.data.entities.AuditInterceptor"/>
<property name="hibernate.max_fetch_depth" value="3"/>
<property name="hibernate.cache.use_query_cache" value="true"/>
<property name="hibernate.cache.use_second_level_cache" value="true"/>
<property name="hibernate.cache.region_prefix" value="region1"/>
<property name="jboss.entity.manager.jndi.name" value="jndiname"/>
<property name="jboss.entity.manager.factory.jndi.name"
value="entityManagerFactory"/>

<mapping resource="auction/Item.hbm.xml"/>
<mapping resource="auction/Category.hbm.xml"/>
<mapping resource="auction/Bid.hbm.xml"/>
</session-factory>
</hibernate-configuration>

Now you can initialize Hibernate using

SessionFactory sessions = new Configuration().configure().buildSessionFactory();

How did Hibernate know where the configuration file was located? When configure() was called, Hibernate searched
for a file named hibernate.cfg.xml in the classpath.

If you wish to use a different filename or have Hibernate look in a subdirectory, you must pass a path to the configure()
method:

SessionFactory session = new Configuration().configure("/hibernate- config/auction.cfg.xml").


buildSessionFactory();

If you have both hibernate.properties and hibernate.cfg.xml in the classpath, the settings of the XML configuration file
will override the settings used in the properties. This is useful if you keep some base settings in properties and override
them for each deployment with an XML configuration file.

You may have noticed that the SessionFactory was also given a name in the XML configuration file. Hibernate uses
this name to automatically bind the SessionFactory to JNDI after creation.

JNDI-bound SessionFactory

A JNDI bound Hibernate Session-Factory can simplify the lookup of the factory and the creation of new Session s.
Note that this is not related to a JNDI bound Datasource, both simply use the same registry!

If you wish to have the Session-Factory bound to a JNDI namespace, specify a name (eg. java:hibernate/Session-
Factory) using the property hibernate.session_factory_name. If this property is omitted, the Session-Factory will not be
bound to JNDI. (This is especially useful in environments with a read-only JNDI default implementation, e.g. Tomcat.)

When binding the Session-Factory to JNDI, Hibernate will use the values of hibernate.jndi.url, hibernate.jndi.class to
instantiate an initial context. If they are not specified, the default InitialContext will be used.

Page 7 of 37
Hibernate will automatically place the Session-Factory in JNDI after you call cfg.buildSessionFactory(). This means
you will at least have this call in some startup code (or utility class) in your application, unless you use JMX
deployment with the Hibernate Service (discussed later).

If you use a JNDI Session-Factory, an EJB or any other class may obtain the Session-Factory using a JNDI lookup.

We recommend that you bind the Session-Factory to JNDI in a managed environment and use a static singleton
otherwise. To shield your application code from these details, we also recommend hiding the actual lookup code for a
Session-Factory in a helper class, such as HibernateUtil.getSessionFactory ().

Persistence lifecycle:

Hibernate defines three states for objects


 Transient
 Persistent
 Detached.

Page 8 of 37
Transient objects:

In Hibernate, objects instantiated using the new operator aren’t immediately persistent. Their state is transient, which
means they aren’t associated with any database table row, and so their state is lost as soon as they’re de-referenced (no
longer referenced by any other object) by the application.
Hibernate considers all transient instances to be non-transactional; a modification to the state of a transient instance
isn’t made in the context of any transaction. This means Hibernate doesn’t provide any rollback functionality for
transient objects.
Objects that are referenced only by other transient instances are, by default, also transient. For an instance to transition
from transient to persistent state requires either a save () call to the persistence manager or the creation of a reference
from an already persistent instance.

Persistent objects:

Persistent instances might be objects instantiated by the application and then made persistent by calling the save ()
method of the persistence manager (the hibernate Session). Persistent instances are then associated with the persistence
manager.
A persistent instance might be an instance retrieved from the database by execution of a query, by an identifier lookup,
or by navigating the object graph starting from another persistent instance. In other words, persistent instances are
always associated with a Session and are transactional.

They might even be objects that became persistent when a reference was created from another persistent object already
associated with a persistence manager.

Page 9 of 37
Persistent instances participate in transactions—their state is synchronized (flushed) with the database at the end of the
transaction. When a transaction commits, state held in memory is propagated to the database by the execution of SQL
INSERT, UPDATE, and DELETE statements.

When the transaction ends, all the persistent object will not be updated to the database. Hibernate checks the objects
and finds which are modified then only it’ll update the database. This process is called dirty checking. Dirty objects are
which has had modified and not synchronized with database. This process gains performance with some databases and
loose performance with some databases. If you only want to update modified columns, you can enable dynamic SQL
generation by setting dynamic-update="true" in a class mapping.

Detached Objects:

In the case of Hibernate, however, these instances lose their association with the persistence manager when you close ()
the Session. We refer to these objects as detached, indicating that their state is no longer guaranteed to be synchronized
with database state; they’re no longer under the management of Hibernate.
Hibernate lets you reuse these instances in a new transaction by re-associating them with a new persistence manager.
(After re-association, they’re considered persistent.) This feature has a deep impact on how multi-tiered applications
may be designed.
Hibernate also provides an explicit detachment operation: the evict () method of the Session. This method will remove
the instance from the session cache. Changes to the instance will not be synchronized with the database. This operation
cascades to associated instances if the association is mapped with cascade="evict". However, this method is typically
used only for cache management (a performance consideration). It’s not normal to perform detachment explicitly.

Making objects persistent

Newly instantiated instances of a persistent class are considered transient by Hibernate. We can make a transient
instance persistent by associating it with a session:

DomesticCat dc = new DomesticCat();


dc.setColor(Color.GINGER);
dc.setSex('M');
dc.setName("Fritz");
Long generatedId = (Long) sess.save(dc);

save () method returns an identifier. If an INSERT has to be executed to get the identifier ( e.g. "identity" generator, not
"sequence"), this INSERT happens immediately, no matter if you are inside or outside of a transaction. This is
problematic in a long-running conversation with an extended Session/persistence context.
Alternatively, you can assign the identifier using an overloaded version of save().

persist() makes a transient instance persistent. This method doesnot return the generated ID.However, it does not
guarantee that the identifier value will be assigned to the persistent instance immediately, the assignment might happen
at flush time. persist() also guarantees that it will not execute an INSERT statement if it is called outside of transaction
boundaries. This is useful in long-running conversations with an extended Session/persistence context.
DomesticCat pk = new DomesticCat();
pk.setColor(Color.TABBY);
pk.setSex('F');
pk.setName("PK");
Page 10 of 37
pk.setKittens( new HashSet() );
pk.addKitten(fritz);
sess.save( pk, new Long(1234) );

Difference between save and persist methods?


save method returns generated identifier where as persist method won't. However calling getId() method after calling
save/persist method will return generated identifier.
If changes are made to transient object after save method is called, it doesnot require to call save/persist method on that
object. Hibernate issues a update statement on that persistent objects.

JPA : Persist vs Merge


Operatio
State Result
n

persist new becomes managed

manag
persist ignored (but cascaded)
ed

remove
persist becomes managed
d

detach throws exception or


persist
ed commit fails

Operatio
State Result
n

merge new becomes managed

manag
merge ignored (but cascaded)
ed

remove throws exception or


merge
d commit fails

detach
merge becomes managed
ed

Automatic dirty checking

Persistent instances are managed in a persistence context.

Page 11 of 37
Objects (state) associated with the persistence context is synchronized with the database at the end of the unit of work /
transaction. When a unit of work completes,state held in memory is propagated to the database by the execution of
SQL INSERT, UPDATE, and DELETE statements (DML). This procedure may also occur at other times. For example,
Hibernate may synchronize with the database before execution of a query. This ensures that queries are aware of
changes made earlier during the unit of work.

Hibernate doesn’t update the database row of every single persistent object in memory at the end of the unit of work.
Hibernate has a strategy for detecting which persistent object have been modified by the application. This is called
automatic dirty checking. An object with modifications that have not yet been propagated to the database is considered
dirty.

Hibernate is able to detect exactly which properties have been modified so that it’s possible to include only the columns
that need updating in the SQL UPDATE statement. This may bring some performance gains. By default, Hibernate
includes all columns of a mapped table in the SQL UPDATE statement (hence, Hibernate can generate this basic SQL
at startup, not at runtime). If you want to update only modified columns, you can enable dynamic SQL generation by
setting dynamic-update="true" in a class mapping.

The same mechanism is implemented for insertion of new records, and you can enable runtime generation of INSERT
statements with dynamic-insert="true". Hibernate excludes columns of mapped table which are null in SQL insert
statement. We recommend you consider this setting when you have an extraordinarily large number of columns in a
table (say, more than 50);

The persistence context cache

A persistence context is a cache of persistent entity instances. This means it remembers all persistent entity instances
you’ve handled in a particular unit of work. Automatic dirty checking is one of the benefits of this caching. Another
benefit is repeatable read for entities and the performance advantage of a unit of work-scoped cache.
For example, if Hibernate is told to load an object by primary key (a lookup by identifier), it can first check the
persistence context for the current unit of work. If the entity is found there, no database hit occurs—this is a repeatable
read for an application. The same is true if a query is executed through one of the Hibernate (or Java Persistence)
interfaces. Hibernate reads the result set of the query and marshals entity objects that are then returned to the
application. During this process, Hibernate interacts with the current persistence context. It tries to resolve every entity
instance in this cache (by identifier); only if the instance can’t be found in the current persistence context does
Hibernate read the rest of the data from the result set.
The persistence context cache offers significant performance benefits and improves the isolation guarantees in a unit of
work (you get repeatable read of entity instances for free). Because this cache only has the scope of a unit of work, it
has no real disadvantages, such as lock management for concurrent access—a unit of work is processed in a single
thread at a time.

The persistence context cache sometimes helps avoid unnecessary database traffic; but, more important, it ensures that:
 The persistence layer isn’t vulnerable to stack overflows in the case of circular references in a graph of objects.
 There can never be conflicting representations of the same database row at the end of a unit of work. In the
persistence context, at most a single object represents any database row. All changes made to that object may
be safely written to the database.
 Likewise, changes made in a particular persistence context are always immediately visible to all other code
executed inside that persistence context and its unit of work (the repeatable read for entities guarantee).
 You don’t have to do anything special to enable the persistence context cache. It’s always on and, for the
reasons shown, can’t be turned off.

Page 12 of 37
Metadata declaration:
<?xml version="1.0"?>
<!DOCTYPE hibernate-mapping PUBLIC "-//Hibernate/Hibernate Mapping DTD//EN"
"http://hibernate.sourceforge.net/hibernate-mapping-2.0.dtd">
<hibernate-mapping>
<class name="org.hibernate.auction.model.Category" table="CATEGORY">
<id name="id" column="CATEGORY_ID" type="long">
<generator class="native"/>
</id>
<property name="name" column="NAME" type="string"/>
</class>
</hibernate-mapping>

Property access strategies:

The access attribute allows you to specify how Hibernate should access property values of the POJO. The default
strategy, property, uses the property accessors (get/set method pair). The field strategy uses reflection to access the
instance variable directly. The following “property” mapping doesn’t require a get/set pair:
<property name="name" column="NAME" type="string" access="field"/>

Controlling insertion and updates

For properties that map to columns, you can control whether they appear in the INSERT statement by using the insert
attribute and whether they appear in the UPDATE statement by using the update attribute.
The following property never has its state written to the database:
<property name="name" column="NAME" type="string" insert="false" update="false"/>
The property name of the Java Bean is therefore immutable and can be read from the database but not modified in any
way. If the complete class is immutable, set the immutable="false" in the class mapping.

In addition, the dynamic-insert attribute tells Hibernate whether to include unmodified property values in an SQL
INSERT, and the dynamic-update attribute tells Hibernate whether to include unmodified properties in the SQL
UPDATE:
<class name="org.hibernate.auction.model.User" dynamic-insert="true" dynamic-update="true">
...
</class>
These are both class-level settings. Enabling either of these settings will cause Hibernate to generate some SQL at
runtime, instead of using the SQL cached at startup time. The performance cost is usually small. Furthermore, leaving
out columns in an insert (and especially in an update) can occasionally improve performance if your tables define many
columns.
Auto generated Object Id:

Many legacy SQL data models use natural primary keys. A natural key is a key with business meaning: an attribute or
combination of attributes that is unique by virtue of its business semantics. Examples of natural keys might be a U.S.
Social Security Number or Australian Tax File Number. Distinguishing natural keys is simple: If a candidate key
attribute has meaning outside the database context, it’s a natural key.

Experience has shown that natural keys almost always cause problems in the long run. For these reasons, we strongly
recommend that new applications use synthetic identifiers (also called surrogate keys). Surrogate keys have no business
Page 13 of 37
meaning— they are unique values generated by the database or application.Hibernate has several built-in identifier
generation strategies.

<?xml version="1.0"?>
<!DOCTYPE hibernate-mapping PUBLIC "-//Hibernate/Hibernate Mapping DTD 3.0//EN"
"http://hibernate.sourceforge.net/hibernate-mapping-3.0.dtd">
<hibernate-mapping>
<class name="Emp" table="EMPLOYEE">
<id name="id" type="long">
<column name="ID" />
<generator class="sequence-identity">
<param name="sequence">KTSEQ_USERGROUP</param>
</generator>
</id>
<property name="name" column="name"/>
</class>
</hibernate-mapping>

increment generates identifiers of type long, short or int that are unique only when no other
process is inserting data into the same table. Do not use in a cluster. .
identity supports identity columns in DB2, MySQL, MS SQL Server, Sybase and
HypersonicSQL. The returned identifier is of type long, short or int.
sequence uses a sequence in DB2, PostgreSQL, Oracle, SAP DB, McKoi or a generator in
Interbase. The returned identifier is of type long, short or int
hilo uses a hi/lo algorithm to efficiently generate identifiers of type long, short or int,
given a table and column (by default hibernate_unique_key and next_hi
respectively) as a source of hi values. The hi/lo algorithm generates identifiers
that are unique only for a particular database.
seqhilo uses a hi/lo algorithm to efficiently generate identifiers of type long, short or int,
given a named database sequence.
uuid uses a 128-bit UUID algorithm to generate identifiers of type string, unique
within a network (the IP address is used). The UUID is encoded as a string of
hexadecimal digits of length 32.
guid uses a database-generated GUID string on MS SQL Server and MySQL.
native picks identity, sequence or hilo depending upon the capabilities of the underlying
database.
assigned lets the application to assign an identifier to the object before save() is called.
This is the default strategy if no <generator> element is specified.
select retrieves a primary key assigned by a database trigger by selecting the row by
some unique key and retrieving the primary key value
foreign uses the identifier of another associated object. Usually used in conjunction with
a <one-to-one> primary key association.

Making an object persistent:

Using save() method:

Page 14 of 37
The first thing you want to do with a Session is make a new transient object persistent.To do so, you use the save()
method:

User user = new User();


user.getName().setFirstname("John");
user.getName().setLastname("Doe");
Session session = sessions.openSession();
Transaction tx = session.beginTransaction();
session.save(user);
tx.commit();
session.close();

Using persist() method:


session.persist(user) : Does the same like session.save().
But session.save() return Serializable object but session.persist() return void.

Updating the persistent state of a detached instance

Modifying the user after the session is closed will have no effect on its persistent representation in the database.
When the session is closed, user becomes a detached instance. It may be reassociated with a new Session by calling
update () or lock ().

user.setPassword("secret");
Session sessionTwo = sessions.openSession();
Transaction tx = sessionTwo.beginTransaction();
sessionTwo.update(user);
user.setUsername("jonny");
tx.commit();
sessionTwo.close();

It doesn’t matter if the object is modified before or after it’s passed to update(). The important thing is that the call to
update() is used to reassociate the detached instance to the new Session (and current transaction) and tells Hibernate to
treat the object as dirty (unless select-before-update is enabled for the persistent class mapping, in which case Hibernate
will determine if the object is dirty by executing a SELECT statement and comparing the object’s current state to the
current database state).
Lock:

Session sessionTwo = sessions.openSession();


Transaction tx = sessionTwo.beginTransaction();
sessionTwo.lock(user, LockMode.NONE);
user.setPassword("secret");
user.setLoginName("jonny");
tx.commit();
sessionTwo.close();
Changes made before the call to lock () aren’t propagated to the database; you only use lock () if you’re sure that the
detached instance hasn’t been modified.

Page 15 of 37
By specifying Lock-Mode.NONE here, we tell Hibernate not to perform a version check or obtain any database-level
locks when reassociating the object with the Session. If we specified LockMode.READ or LockMode.UPGRADE,
Hibernate would execute a SELECT statement in order to perform a version check (and to set an upgrade lock).

Retrieving a persistent object


The Session is also used to query the database and retrieve existing persistent objects. However, special methods are
provided on the Session API for the simplest kind of query: retrieval by identifier. One of these methods is get(),
demonstrated here:
Session session = sessions.openSession();
Transaction tx = session.beginTransaction();
int userID = 1234;
User user = (User) session.get(User.class, new Long(userID));
tx.commit();
session.close();
The retrieved object user may now be passed to the presentation layer for use outside the transaction as a detached
instance (after the session has been closed). If no row with the given identifier value exists in the database, the get()
returns null.
Updating a persistent object
Any persistent object returned by get() or any other kind of query is already associated with the current Session and
transaction context. It can be modified, and its state will be synchronized with the database. This mechanism is called
automatic dirty checking, which means Hibernate will track and save the changes you make to an object inside a
session:
Session session = sessions.openSession();
Transaction tx = session.beginTransaction();
int userID = 1234;
User user = (User) session.get(User.class, new Long(userID));
user.setPassword("secret");
tx.commit();
session.close();
First we retrieve the object from the database with the given identifier. We modify the object, and these modifications
are propagated to the database when tx.commit() is called. Of course, as soon as we close the Session, the instance is
considered detached.

Making a persistent object transient


You can easily make a persistent object transient, removing its persistent state from the database, using the delete()
method:
Session session = sessions.openSession();
Transaction tx = session.beginTransaction();
int userID = 1234;
User user = (User) session.get(User.class, new Long(userID));
session.delete(user);
tx.commit();
session.close();

The SQL DELETE will be executed only when the Session is synchronized with the database at the end of the
transaction.After the Session is closed, the user object is considered an ordinary transient instance. The transient
Page 16 of 37
instance will be destroyed by the garbage collector if it’s no longer referenced by any other object. Both the in-
memory object instance and the persistent database row will have been removed.

Making a detached object transient


Finally, you can make a detached instance transient, deleting its persistent state from the database. This means you
don’t have to reattach (with update () or lock ()) a detached instance to delete it from the database; you can directly
delete a detached instance:
Session session = sessions.openSession();
Transaction tx = session.beginTransaction();
session.delete(user);
tx.commit();
session.close();
In this case, the call to delete () does two things: It associates the object with the Session and then schedules the object
for deletion, executed on tx.commit().

Retrieving objects by identifier


The following Hibernate code snippet retrieves a User object from the database:
User user = (User) session.get(User.class, userID);

The get() method is special because the identifier uniquely identifies a single instance of a class. Hence it’s common for
applications to use the identifier as a convenient handle to a persistent object. Retrieval by identifier can use the cache
when retrieving an object, avoiding a database hit if the object is already cached.
Hibernate also provides a load() method:
User user = (User) session.load(User.class, userID);
The load() method is older; get() was added to Hibernate’s API due to user request.
The difference is trivial:
1. If load() can’t find the object in the cache or database, an exception is thrown. The load() method never returns
null. The get() method returns null if the object can’t be found.
2. The load() method may return a proxy instead of a real persistent instance.A proxy is a placeholder that triggers
the loading of the real object when it’s accessed for the first time. On the other hand, get() never returns a
proxy.
Choosing between get() and load() is easy:
If you’re certain the persistent object exists, load() is a good option. If you aren’t certain there is a persistent
instance with the given identifier, use get() and test the return value to see if it’s null.
Using load() has a further implication:
The application may retrieve a valid reference (a proxy) to a persistent instance without hitting the database to
retrieve its persistent state. So load() might not throw an exception when it doesn’t find the persistent object in the
cache or database; the exception would be thrown later, when the proxy is accessed.

Distinguishing between transient and detached instances


Hibernate will assume that an instance is an unsaved transient instance if:
1) The identifier property (if it exists) is null.
2) The version property (if it exists) is null.
3) You supply an unsaved-value in the mapping document for the class, and the value of the identifier property
matches.
4) You supply an unsaved-value in the mapping document for the version property, and the value of the version
property matches.

Page 17 of 37
5) You supply a Hibernate Interceptor and return Boolean.TRUE from Interceptor.isUnsaved() after checking the
instance in your code.

Detached instances have a non-null identifier value, so Hibernate treats them properly too.

if we had used the primitive type long in our persistent classes, we would have needed to use the following identifier
mapping in all our classes:
<id name="id" type="long" column="ID" unsaved-value="0">
<generator class="native"/>
</id>

The unsaved-value attribute tells Hibernate to treat instances of Category with an identifier value of 0 as newly
instantiated transient instances. The default value for the attribute unsaved-value is null;
The solution to this problem is using primitive wrapper class as our ID type (java.lang.Long in this case). In such case,
“null” will be treated as unsaved value.

Transitive Persistence:

Transitive persistence is a technique that allows you to propagate persistence to transient and detached sub-graphs
automatically.
Persistence by reachability is one of the models of Transitive persistence.
Persistence by reachability:
Persistence by reachability is a recursive algorithm. All objects reachable from a persistent instance become
persistent either when the original instance is made persistent or just before in-memory state is synchronized with the
data store.
In the purest form of persistence by reachability, the database has some top-level, or root, object from which all
persistent objects are reachable. Ideally, an instance should become transient and be deleted from the database if it isn’t
reachable via references from the root persistent object.
Neither Hibernate nor other ORM solutions implement this form.
Persistence by reachability is at best a halfway solution. It helps you make transient objects persistent and
propagate their state to the database without many calls to the persistence manager. But it isn’t a full solution to the
problem of making persistent objects transient and removing their state from the database. You can’t simply remove all
reachable instances when you remove an object; other persistent instances may hold references to them. It's difficult to
implement.

Cascading persistence with Hibernate


Hibernate’s transitive persistence model uses the same basic concept as persistence by reachability—that is,
object associations are examined to determine transitive state. However, Hibernate allows you to specify a cascade
style for each association mapping, which offers more flexibility and fine-grained control for all state transitions.
Hibernate reads the declared style and cascades operations to associated objects automatically.
By default, Hibernate does not navigate an association when searching for transient or detached objects, so
saving, deleting, or reattaching a Category won’t affect the child category objects. This is the opposite of the
persistence-by-reachability default behavior.

You can map entity associations in metadata with the following attributes:
1) cascade="none", the default, tells Hibernate to ignore the association.

Page 18 of 37
2) cascade="save-update" tells Hibernate to navigate the association when the transaction is committed and when
an object is passed to save() or update() and save newly instantiated transient instances and persist changes to
detached instances.
3) cascade="delete" tells Hibernate to navigate the association and delete persistent instances when an object is
passed to delete().
4) cascade="delete-orphan" Hibernate will delete any persistent entity instance that has been removed (de-
referenced) from the association (for example, from a collection).
5) cascade="all" means to cascade both save-update and delete, as well as calls to evict and lock.
6) cascade="all-delete-orphan" means the same as cascade="all" but, in addition, Hibernate deletes any persistent
entity instance that has been removed (dereferenced) from the association (for example, from a collection).
7)
Fetching strategies:
Fetching strategy defines how an associated object or a collection should be loaded, when the owning entity
object is loaded, and when you access an associated object or collection.
The problem of fetching object graphs efficiently (with minimal access to the database) has often been
addressed by providing association-level fetching strategies specified in metadata of the association mapping.
Hibernate allows you to choose among four fetching strategies for any association, in association metadata and
at runtime:
1) Immediate fetching—The associated object is fetched immediately, using a sequential database read (or cache
lookup).
2) Lazy fetching—The associated object or collection is fetched “lazily,” when it’s first accessed. This results in a
new request to the database (unless the associated object is cached).
3) Eager fetching—The associated object or collection is fetched together with the owning object, using an SQL
outer join, and no further database request is required.
4) Batch fetching—This approach may be used to improve the performance of lazy fetching by retrieving a batch
of objects or collections when a lazy association is accessed. (Batch fetching may also be used to improve the
performance of immediate fetching.)

Lazy fetching:
Hibernate defaults to a lazy fetching strategy for all entities and collections. This means that Hibernate by
default loads only the objects you’re querying for.
If you query for an Item object (let’s say you load it by its identifier), exactly this Item and nothing else is loaded into
memory:
Item item = (Item) session.load(Item.class, new Long(123));
This retrieval by identifier results in a single SQL statement that retrieves an Item instance. In the persistence context,
in memory, you now have this item object available in persistent state.

Understanding proxies:
Hibernate proxies are instances of runtime generated subclasses of your entity classes.
A proxy is initialized if you call any method other than identifier getter method (getId ()), a collection is initialized if
you start iterating through its elements or if you call any of the collection-management operations, such as size () and
contains ().

1) Item item = (Item) session.load(Item.class, new Long(123));


2) item.getId();
3) item.getDescription(); // Initialize the proxy

Page 19 of 37
The third line in this example triggers the execution of the SQL that retrieves an Item into memory. As long as you
access only the database identifier property, no initialization of the proxy is necessary. (Note that this isn’t true if you
map the identifier property with direct field access; Hibernate then doesn’t even know that the getId() method exists. If
you call it, the proxy has to be initialized.)

A proxy is useful if you need the Item only to create a reference, for example:
Item item = (Item) session.load(Item.class, new Long(123));
User user = (User) session.load(User.class, new Long(1234));
Bid newBid = new Bid("99.99");
newBid.setItem(item);
newBid.setBidder(user);
session.save(newBid);

You first load two objects, an Item and a User. Hibernate doesn’t hit the database to do this: It returns two proxies. This
is all you need, because you only require the Item and User to create a new Bid. The save(new bid) call executes an
INSERT statement to save the row in the BID table with the foreign key value of an Item and a User—this is all the
proxies can and have to provide. The previous code snippet doesn’t execute any SELECT!
If you call get () instead of load () you trigger a database hit and no proxy is returned. The get () operation always hits
the database (if the instance isn’t already in the persistence context and if no transparent second-level cache is active)
and returns null if the object can’t be found.

A JPA provider can implement lazy loading with proxies. The method names of the operations that are equivalent to
load() and get() on the EntityManager API are find() and getReference():
Item item = em.find(Item.class, new Long(123));
Item itemRef = em.getReference(Item.class, new Long(1234));

The first call, find (), has to hit the database to initialize an Item instance. No proxies are allowed—it’s the equivalent
of the Hibernate get () operation. The second call, getReference (), may return a proxy, but it doesn’t have to—which
translates to load() in Hibernate.

Hibernate provides an additional setting that is mostly useful for large collections; they can be mapped as extra lazy.
For example, consider the collection of bids of an Item:

<class name="Item" table="ITEM">


...
<set name="bids" lazy="extra" inverse="true">
<key column="ITEM_ID"/>
<one-to-many class="Bid"/>
</set>
</class>

The collection wrapper is now smarter than before. The collection is no longer initialized if you call size (), contains (),
or isEmpty ()—the database is queried to retrieve the necessary information. If it’s a Map or a List, the operations
containsKey() and get() also query the database directly.

Disabling proxy generation:


You can disable proxy generation for a particular entity class with the lazy="false" attribute in XML mapping
metadata:
Page 20 of 37
<class name="User" table="USERS" lazy="false">
...
</class>

Eager loading of associations and collections:


Hibernate is lazy by default. All associated entities and collections aren’t initialized if you load an entity object.
In Hibernate XML mapping metadata you’d map the association from Item to User as lazy="false":
<class name="Item" table="ITEM">
...
<many-to-one name="seller" class="User" column="SELLER_ID" update="false" not-
null="true" lazy="false"/>
...
</class>
The same “always load” guarantee can be applied to collections—for example, all bids of an Item:
<class name="Item" table="ITEM">
...
<many-to-one name="seller" lazy="false" .../>
<set name="bids" lazy="false" inverse="true">
<key column="ITEM_ID"/>
<one-to-many class="Bid"/>
</set>
...
</class>
If you now get () an Item (or force the initialization of a proxied Item), both the seller object and all the bids are loaded
as persistent instances into your persistence context:
Item item = (Item) session.get(Item.class, new Long(123));

The FetchType.EAGER provides the same guarantees as lazy="false" in Hibernate: the associated entity instance must
be fetched eagerly, not lazily.
Although all associations in Hibernate are completely lazy, but in JPA all @ManyToOne and @OneToOne
associations default to FetchType.EAGER!.

Selecting a fetch strategy:


The goal of selecting fetch strategy is minimize the number of SQL statements and to simplify the SQL statements, so
that querying can be as efficient as possible.
By default, Hibernate fetches associated objects and collections lazily whenever you access them. You need to map all
to-one associations as FetchType.LAZY if you use Java Persistence.
Item item = (Item) session.get(Item.class, new Long(123));

select item.* from ITEM item where item.ITEM_ID = ?

You can see that the SELECT queries only the ITEM table and retrieves a particular row. All entity associations and
collections aren’t retrieved. If you access any proxied association or uninitialized collection, a second SELECT is
executed to retrieve the data on demand.
Batch fetching:
If every entity association and collection is fetched only on demand, many additional SQL SELECT statements may be
necessary to complete a particular procedure.
For example, consider the following query that retrieves all Item objects and accesses the data of each items seller:
Page 21 of 37
List allItems = session.createQuery("from Item").list();
processSeller( (Item)allItems.get(0) ); //Get the seller object
processSeller( (Item)allItems.get(1) );
processSeller( (Item)allItems.get(2) );

Naturally, you use a loop here and iterate through the results, but the problem this code exposes is the same. You see
one SQL SELECT to retrieve all the Item objects, and an additional SELECT for every seller of an Item as soon as you
process it. All associated User objects are proxies. This is one of the worst-case scenarios we’ll describe later in more
detail: the n+1 selects problem. This is what the SQL looks like:
select items...
select u.* from USERS u where u.USER_ID = ?
select u.* from USERS u where u.USER_ID = ?
select u.* from USERS u where u.USER_ID = ?

The first optimization we now discuss is called batch fetching, and it works as follows: If one proxy of a User must be
initialized, batch-fetching will initialize several (based on batch-size) in the same SELECT.
If there are three Item instances in the persistence context, and that they all have a proxy applied to their seller
association, you may as well initialize all the proxies instead of just one.
<class name="User" table="USERS" batch-size="10">
...
</class>

You’re telling Hibernate to pre-fetch up to 10 uninitialized proxies in a single SQL SELECT, if one proxy must be
initialized. The resulting SQL for the earlier query and procedure may now look as follows:
select items...
select u.* from USERS u where u.USER_ID in (?, ?, ?)

The first statement that retrieves all Item objects is executed when you list () the query. The next statement, retrieving
three User objects, is triggered as soon as you initialize the first proxy returned by allItems.get (0).getSeller (). This
query loads three sellers at once—because this is how many items the initial query returned and how many proxies are
uninitialized in the current persistence context. You defined the batch size as “up to 10.” If more than 10 items are
returned, you see how the second query retrieves 10 sellers in one batch. If the application hits another proxy that
hasn’t been initialized, a batch of another 10 is retrieved— and so on, until no more uninitialized proxies are left in the
persistence context or the application stops accessing proxied objects.

Batch fetching is also available for collections:

<class name="Item" table="ITEM">


...
<set name="bids" inverse="true" batch-size="10">
<key column="ITEM_ID"/>
<one-to-many class="Bid"/>
</set>
</class>

If you now force the initialization of one bids collection, up to 10 more collections of the same type, if they’re
uninitialized in the current persistence context, are loaded right away:
select items...
Page 22 of 37
select b.* from BID b where b.ITEM_ID in (?, ?, ?)

In this case, you again have three Item objects in persistent state, and touching one of the unloaded bids collections.
Now all three Item objects have their bids loaded in a single SELECT.

Sub-select fetching:
A much better optimization is subselect fetching for this collection mapping:
<class name="Item" table="ITEM">
...
<set name="bids" inverse="true" fetch="subselect">
<key column="ITEM_ID"/>
<one-to-many class="Bid"/>
</set>
</class>
Hibernate now initializes all bids collections for all loaded Item objects, as soon as you force the initialization of one
bids collection. It does that by rerunning the first initial query (slightly modified) in a
subselect:
select i.* from ITEM i
select b.* from BID b where b.ITEM_ID in (select i.ITEM_ID from ITEM i)

Eager fetching with joins:


If you need a object and associated object everytime you query, then eager-fectch is good option.
For enabling eager fetching
<class name="Item" table="ITEM">
...
<many-to-one name="seller" class="User" column="SELLER_ID" update="false" fetch="join"/>
</class>
Hibernate now loads both an Item and its seller in a single SQL statement. For example:

Item item = (Item) session.get(Item.class, new Long(123));

This operation triggers the following SQL SELECT:


select i.*, u.* from ITEM i
left outer join USERS u on i.SELLER_ID = u.USER_ID
where i.ITEM_ID = ?

Obviously, the seller is no longer lazily loaded on demand, but immediately. Hence, a fetch="join" disables lazy
loading.
If you only enable eager fetching with lazy="false", you see an immediate second SELECT for the user object.
If you enable <many-to-one not-null="true"/>, Hibernate executes an inner join instead of an outer join.

You can also set the eager join fetching strategy on a collection:
<class name="Item" table="ITEM">
...
<set name="bids" inverse="true" fetch="join">
<key column="ITEM_ID"/>
<one-to-many class="Bid"/>

Page 23 of 37
</set>
</class>

select i.*, b.* from ITEM i left outer join BID b on i.ITEM_ID = b.ITEM_ID

The resultset now contains many rows, with duplicate data for each Item that has many bids, and NULL fillers for all
Item objects that don’t have bids.
The number of tables joined in this case depends on the global hibernate. max_fetch_depth configuration property. By
default, no limit is set, so loading an Item also retrieves a Bid, a User, and an Address in a single select. Reasonable
settings are small, usually between 1 and 5. You may even disable join fetching for many-to-one and one-to-one
associations by setting the property to 0!

The n+1 selects problem:


The n+1 selects problem is easy to understand with some example code. Let’s assume that you don’t configure any
fetch plan or fetching strategy in your mapping metadata: Everything is lazy and loaded on demand.
List<Item> allItems = session.createQuery("from Item").list();
// List<Item> allItems = session.createCriteria(Item.class).list();
Map<Item, Bid> highestBids = new HashMap<Item, Bid>();
for (Item item : allItems) {
Bid highestBid = null;
for (Bid bid : item.getBids() ) { // Initialize the collection
if (highestBid == null)
highestBid = bid;
if (bid.getAmount() > highestBid.getAmount())
highestBid = bid;
}
highestBids.put(item, highestBid);
}

What you access is the bids collection of each Item. This collection isn’t initialized so far, the Bid objects for each item
have to be loaded with an additional query. This whole code snippet therefore produces n+1 selects.

Avoiding n+1 selects:


1) Use batch-fetching:
A first solution could be a change of your global mapping metadata for the collection, enabling prefetching in batches:
<set name="bids" inverse="true" batch-size="10">
<key column="ITEM_ID"/>
<one-to-many class="Bid"/>
</set>
Instead of n+1 selects, you now see (n/10)+1 selects to retrieve the required collections into memory.

2) With a subselect-based prefetch, you can reduce the number of selects to exactly two:
<set name="bids" inverse="true" fetch="subselect">
<key column="ITEM_ID"/>
<one-to-many class="Bid"/>
</set>
3) We dont consider fetch="join" a common optimization for collection mappings as it will result in higher
memory consumption,
Page 24 of 37
every OUTER JOINed collection is a step toward a more serious Cartesian product problem.

The fetch="join" setting on <many-to-one> or <one-to-one> association is a common optimization, as is a


@ManyToOne(fetch = FetchType.EAGER) annotation (which is the default in Java Persistence). Eager join fetching of
single-ended associations, unlike eager outer-join fetching of collections, doesn’t create a Cartesian product problem.

Cartesian product problem:

This Cartesian product problem always appears if you try to fetch several “parallel” collections. The Item class has
more than one many-to-one association of bids an images with fetch="join".
<class name="Item">
...
<set name="bids" inverse="true" fetch="join">
<key column="ITEM_ID"/>
<one-to-many class="Bid"/>
</set>
<set name="images" fetch="join">
<key column="ITEM_ID"/>
<composite-element class="Image">...
</set>
</class>

Result:
Hibernate executes an SQL SELECT that creates a product of the two collections:
select item.*, bid.*, image.*
from ITEM item
left outer join BID bid on item.ITEM_ID = bid.ITEM_ID
left outer join ITEM_IMAGE image on item.ITEM_ID = image.ITEM_ID
This resultset contains lots of redundant data.

Forcing proxy and collection initialization:


You can use the static method Hibernate.initialize() for manual initialization of a proxy:
Session session = sessionFactory.openSession();
Transaction tx = session.beginTransaction();
Item item = (Item) session.get(Item.class, new Long(1234));
Hibernate.initialize( item.getSeller() );
tx.commit();
session.close();
processDetached( item.getSeller() );
...
Hibernate.initialize () may be passed a collection wrapper or a proxy. Note that if you pass a collection wrapper to
initialize (), it doesn’t initialize the target entity objects that are referenced by this collection. In the previous example,
Hibernate.initalize (item.getBids ()) wouldn’t load all the Bid objects inside that collection. It initializes the collection
with proxies of Bid objects!

Set fetch="join" on many-to-one and one-to-one association mappings. In rare cases, if you’re absolutely sure, enable
fetch="join" to disable lazy loading for particular collections.

Page 25 of 37
Hibernate associations:

If the association is navigable from one object to other it is uni-directional association. If the association is
navigable from both ends it is bi-directional association.

Many-to-one association:
public class Book {
private Long id;
private String isbn;
private String name;
private Publisher publisher;
private Date publishDate;
private Integer price;
private List chapters;
// Getters and Setters
}

To make use of this property, we can add a <many-to-one> mapping to the mapping definition of Book class. This will
add a column PUBLISHER_ID in the BOOK table and store the ID of associated publisher. Don’t forget to run the
schema update task for reflecting the changes to database.
<hibernate-mapping package="mo.org.cpttm.bookshop">
<class name="Book" table="BOOK">
<id name="id" type="long" column="ID">
<generator class="native"/>
</id>
<property name="isbn" type="string">
<column name="ISBN" length="50" not-null="true" unique="true" />
</property>
<property name="name" type="string">
<column name="BOOK_NAME" length="100" not-null="true" />
</property>
<property name="publishDate" type="date" column="PUBLISH_DATE" />
<property name="price" type="int" column="PRICE" />
<many-to-one name="publisher" class="Publisher" column="PUBLISHER_ID" />
</class>
</hibernate-mapping>

By default the lazy attribute of the association is true. so if we get book object, publisher will be loaded lazily means
proxy is retrieved along with book object.
Session session = factory.openSession();
try {
Book book = (Book) session.get(Book.class, id);
return book;
} finally {
session.close();
}
But when we access the publisher object through book.getPublisher() outside this method, lazy initialization exception
will occur.
Page 26 of 37
System.out.println(book.getName());
System.out.println(book.getPublisher().getName());
If we want the publisher object can be accessed outside the session, there will be two possible solutions.
One is to initialize the publisher explicitly, we can call the method Hibernate.initialize() for this task. This will force the
publisher object to be loaded from database.
Session session = factory.openSession();
try {
Book book = (Book) session.get(Book.class, id);
Hibernate.initialize(book.getPublisher());
return book;
} finally {
session.close();
}
Another solution is to turn off the lazy initialization feature for this association. This may decrease
the performance as the publisher object will be loaded together with the book object every time.
<hibernate-mapping package="mo.org.cpttm.bookshop">
<class name="Book" table="BOOK">
...
<many-to-one name="publisher" class="Publisher" column="PUBLISHER_ID"
lazy="false" />
</class>
</hibernate-mapping>

Making lazy= “false” we generate two select queries one for book and other for publisher. To optimize this we have to
include fetch strategies.
Fetch strategy:

To ask Hibernate to retrieve the information in one shot, i.e. issue a single SELECT statement with table join, we can
change the “fetch” attribute of the association to “join” (default is “select”).

<hibernate-mapping package="mo.org.cpttm.bookshop">
<class name="Book" table="BOOK">
...
<many-to-one name="publisher" class="Publisher" column="PUBLISHER_ID"
lazy="false" fetch="join" />
</class>
</hibernate-mapping>

If we inspect the SQL statements again, we will find that Hibernate is using a single SELECT statement with table join
to get the information. But is it also the case for using HQL queries?
Session session = factory.openSession();
try {
Query query = session.createQuery("from Book where isbn = ?");
query.setString(0, isbn);
Book book = (Book) query.uniqueResult();
return book;
} finally {
session.close();
Page 27 of 37
}
Unfortunately, two SELECT statements are still executing for this case. It is because any HQL query will be translated
into SQL statement directly. To apply the joining fetch strategy, we need to use the following HQL syntax.
Session session = factory.openSession();
try {
Query query = session.createQuery("from Book book left join fetch book.publisher where book.isbn
= ?");
query.setString(0, isbn);
Book book = (Book) query.uniqueResult();
return book;
} finally {
session.close();
}

Using left join fetching in HQL can also force the association to be initialized, if it is lazy. This is often used for
initializing lazy objects so that they can be accessed outside the session.

<many-to-one name="publisher" class="Publisher" column="PUBLISHER_ID" lazy="false"


fetch="join" />

Cascading the association


After we have created a new book object together with a new publisher object, we want to save
them into the database. Will Hibernate save the publisher object also when we save the book object?
Unfortunately, an exception will occur if you save the book object only. That means we must save
them one by one.
Session session = factory.openSession();
Transaction tx = null;
try {
tx = session.beginTransaction();
session.save(publisher);
session.save(book);
tx.commit();
} catch (HibernateException e) {
if (tx != null) tx.rollback();
throw e;
} finally {
session.close();
}
Isn’t it very trouble saving all the objects one by one, especially for a large object graph?
Undoubtedly, Hibernate is providing a way for saving them in one shot. Let’s add a cascade="save-update" attribute to
the <many-to-one> mapping. Hibernate will cascade the save/update operations to the associated object as well.
<hibernate-mapping package="mo.org.cpttm.bookshop">
<class name="Book" table="BOOK">
...
<many-to-one name="publisher" class="Publisher" column="PUBLISHER_ID" cascade="save-
update" />
</class>
</hibernate-mapping>
Page 28 of 37
The save/update cascading is very useful when we persist a graph of objects, which some of them are newly created,
while some are updated. We can use the saveOrUpdate() method and let Hibernate to decide which objects should be
created and which should be updated.
session.saveOrUpdate(book);
In additional to save/update cascading, we can also cascade the delete operation.
<many-to-one name="publisher" class="Publisher" column="PUBLISHER_ID" cascade="save-
update,delete" />

Cascading the association


After we have created a new book object together with a new publisher object, we want to save
them into the database. Will Hibernate save the publisher object also when we save the book object?
Unfortunately, an exception will occur if you save the book object only. That means we must save
them one by one.
Session session = factory.openSession();
Transaction tx = null;
try {
tx = session.beginTransaction();
session.save(publisher);
session.save(book);
tx.commit();
} catch (HibernateException e) {
if (tx != null) tx.rollback();
throw e;
} finally {
session.close();
}
Isn’t it very trouble saving all the objects one by one, especially for a large object graph?
Undoubtedly, Hibernate is providing a way for saving them in one shot. Let’s add a cascade="save-update" attribute to
the <many-to-one> mapping. Hibernate will cascade the save/update operations to the associated object as well.
<hibernate-mapping package="mo.org.cpttm.bookshop">
<class name="Book" table="BOOK">
...
<many-to-one name="publisher" class="Publisher" column="PUBLISHER_ID" cascade="save-
update" />
</class>
</hibernate-mapping>
The save/update cascading is very useful when we persist a graph of objects, which some of them are newly created,
while some are updated. We can use the saveOrUpdate() method and let Hibernate to decide which objects should be
created and which should be updated.
session.saveOrUpdate(book);
In additional to save/update cascading, we can also cascade the delete operation.
<many-to-one name="publisher" class="Publisher" column="PUBLISHER_ID" cascade="save-update,delete"
/>
Using a join table for many-to-one association
For the previous many-to-one association, we were adding a column PUBLISHER_ID to the BOOK table. There is
another way of structuring the tables. We can ask Hibernate to use an additional table BOOK_PUBLISHER to store the
relationship of these two kinds of objects. This table is called a “join table”. The optional=“true” attribute means that a
row is inserted to this table only when the association is not null.
Page 29 of 37
<hibernate-mapping package="mo.org.cpttm.bookshop">
<class name="Book" table="BOOK">
...
<many-to-one name="publisher" class="Publisher" column="PUBLISHER_ID" />
<join table="BOOK_PUBLISHER" optional="true">
<key column="BOOK_ID" unique="true" />
<many-to-one name="publisher" class="Publisher" column="PUBLISHER_ID" not-
null="true" />
</join>
</class>
</hibernate-mapping>

One-to-one Association:
The simplest way of mapping a one-to-one association is to treat it as a many-to-one association, but add a unique
constraint on it. You can declare the lazy, fetch and cascade attributes in the same way.
<hibernate-mapping package="mo.org.cpttm.bookshop">
<class name="Customer" table="CUSTOMER">
...
<many-to-one name="address" class="Address" column="ADDRESS_ID" unique="true" cascade="save-
update,delete" />
</class>
</hibernate-mapping>

We have mapped the unidirectional association from customer to address. If we want to make this
association bi-directional, we can map this association in the address side as a one-to-one
association, which references the “address” property of the Customer class.
public class Address {
private Long id;
private String city;
private String street;
private String doorplate;
private Customer customer;
// Getters and Setters
}
<hibernate-mapping>
<class name="Address" table="ADDRESS">
...
<one-to-one name="customer" class="Customer" property-ref="address" />
</class>
</hibernate-mapping>
Primary key association
The second way of mapping a one-to-one association is to let both objects have the same ID.Suppose we choose the
customer as the master object so that its ID is auto-generated. Then in the Address mapping definition, we declare the
ID as “foreign” type which references the customer property. Each address object will be assigned the same ID as its
customer. The “constrained” attribute means that the ID of Address has a foreign key constraint to the ID of Customer.
<hibernate-mapping package="mo.org.cpttm.bookshop">
<class name="Customer" table="CUSTOMER">
<id name="id" type="long" column="ID">
Page 30 of 37
<generator class="native"/>
</id>
...
<one-to-one name="address" class="Address" cascade="save-update,delete" />
</class>
</hibernate-mapping>
<hibernate-mapping>
<class name="Address" table="ADDRESS">
<id name="id" column="ID">
<generator class="foreign">
<param name="property">customer</param>
</generator>
</id>
...
<one-to-one name="customer" class="Customer" constrained="true" />
</class>
</hibernate-mapping>
For making a bi-directional association, you can declare a <one-to-one> mapping at both sides. If you want a
unidirectional association, you can omit the <one-to-one> mapping in the customer side but not the address side. That
means this association is only navigable from address to customer if it
is made unidirectional. If this is not what you want, you can reverse the declaration of <id> and <one-to-one>
mappings at both sides.

Using a join table


The last method of mapping a one-to-one association is using a join table just like many-to-one association. There is
nothing different unless both the <key> and <many-to-one> mappings need a unique constraint. This method is seldom
used.
<hibernate-mapping package="mo.org.cpttm.bookshop">
<class name="Customer" table="CUSTOMER">
<many-to-one name="address" class="Address" column="ADDRESS_ID" unique="true"
cascade="save-update" />
<join table="CUSTOMER_ADDRESS" optional="true">
<key column="CUSTOMER_ID" unique="true" />
<many-to-one name="address" class="Address" column="ADDRESS_ID" not-
null="true" unique="true" cascade="save-update,delete" />
</join>
</class>
</hibernate-mapping>
To make this association bi-directional, you can add the opposite mapping definition in the Address side, except for the
cascade attribute.
<hibernate-mapping package="mo.org.cpttm.bookshop">
<class name="Address" table="ADDRESS">
...
<one-to-one name="customer" class="Customer" property-ref="address" />
<join table="CUSTOMER_ADDRESS" optional="true">
<key column="ADDRESS_ID" unique="true" />
<many-to-one name="customer" class="Customer" column="CUSTOMER_ID" not-
null="true" unique="true" />
Page 31 of 37
</join>
</class>
</hibernate-mapping>
But if you try to save this kind of object graph to the database, you will get an error. This is because Hibernate will save
each side of the association in turn. For the Customer side association, a row will be inserted into the
CUSTOMER_ADDRESS table successfully. But for the Address side association, the same row will be inserted into
the same table so that a unique constraint violation occurred.
To avoid saving the same association for two times, we can mark either side of the association as “inverse”. Hibernate
will ignore this side of association when saving the object.
<hibernate-mapping package="mo.org.cpttm.bookshop">
<class name="Address" table="ADDRESS">
...
<join table="CUSTOMER_ADDRESS" optional="true" inverse="true">
<key column="ADDRESS_ID" unique="true" />
<many-to-one name="customer" class="Customer" column="CUSTOMER_ID" not-
null="true" unique="true" />
</join>
</class>
</hibernate-mapping>

Named queries:
Hibernate allows queries to be defined in the mapping files.
<sql-query name= “ ”>
<![CDATA[

]]>
</sql-query>

Query query = session.getNamedQuery(queryname);

Native queries:
Queries can also be expressed in native dialect of the database. This is useful if you want database specific
features.
session.creatSQLQuery(“query”)

Pagination:
Collections are pageable by using the Query interface with a filter:
Query q = s.createFilter( collection, "" ); // the trivial filter
q.setMaxResults(PAGE_SIZE);
q.setFirstResult(PAGE_SIZE * pageNumber);
List page = q.list();

Criteria Queries:
The interface org.hibernate.Criteria is used to query against a particular persistent class.
Criteria crit = sess.createCriteria(Cat.class);
crit.setMaxResults(50);
Page 32 of 37
List cats = crit.list();
An individual query criterion is an instance of the interface org.hibernate.criterion.Criterion. The class
org.hibernate.criterion.Restrictions defines factory methods for obtaining certain built-in Criterion
types.
List cats = sess.createCriteria(Cat.class)
.add( Restrictions.like("name", "Fritz%") )
.add( Restrictions.between("weight", minWeight, maxWeight) )
.list();

Ordering the results


You may order the results using org.hibernate.criterion.Order.
List cats = sess.createCriteria(Cat.class)
.add( Restrictions.like("name", "F%")
.addOrder( Order.asc("name") )
.addOrder( Order.desc("age") )
.setMaxResults(50)
.list();

List cats = sess.createCriteria(Cat.class)


.add( Property.forName("name").like("F%") )
.addOrder( Property.forName("name").asc() )
.addOrder( Property.forName("age").desc() )
.setMaxResults(50)
.list();

Dynamic association fetching


You may specify association fetching semantics at runtime using setFetchMode().
List cats = sess.createCriteria(Cat.class)
.add( Restrictions.like("name", "Fritz%") )
.setFetchMode("mate", FetchMode.EAGER)
.setFetchMode("kittens", FetchMode.EAGER)
.list();
This query will fetch both mate and kittens by outer join. See Section 20.1, “Fetching strategies” for more information.

Projections:
Do not confuse the term "Projection" as it is used here with the Projection class. Projection in common terms means to
retrieve, and in SQL it means the "Select" clause. The "Select" clause is just a part of the services provided by the
Projection class. Following is SQL query for projection of all fields of the ORDER table in SQL:

SELECT * FROM ORDER

The Criteria equivalent would be:

List orders= session.createCriteria(Order.class).list();

Page 33 of 37
The above statement executes the corresponding SQL statement at the database server, populates the instances of the
Order ORM class, adds them to a list and returns the List object. Actually, the above statement is composed of two
statements:

Criteria criteria= session.createCriteria(Order.class) and

List orders=criteria.list().

The combination of such dependent statements is known as method chaining. From now on I will be using this
technique extensively. The above code retrieves all the rows from the ORDER table. But what if only the data
contained in one of the fields has to be retrieved, as in the following SQL query:

SELECT NAME FROM PRODUCT

Here, the Projection class comes into play. The above query can be rewritten into a Criteria query as:

List products=session.createCriteria(Product.class)
. setProjection(Projections.property(\"name\"))
.list();

above query returns list of property type values i.e list of strings.
It is clear from the above example that to query based on just one field, the fieldname is passed as an argument to the
property() method of the Projection class. The Projection instance returned in turn becomes an argument to the
setProjection() method. Similarly, to retrieve data based on two fields, ProjectionList has to be used. Hence the SQL
query:

“SELECT NAME, ID FROM PRODUCT” Would become

List products =session.createCriteria(Product.class).setProjection(


Projections.propertyList()
.add(Projection.property(\"name\"))
.add(Projection.property(\"id\"))
)
.list();
above query returns list of object array (Object[])

Optimistic Locking and Versioning in Hibernate


What is optimistic locking?

Optimistic locking is a method used to prevent simultaneously access problem on the same entity for change, which
does not lock on the database level, in order to maintain the correct data.
For example, if two user wants to update same entity in different transactions, when first one saves and then second one
saves without getting updates from the first user’s change, who will be the winner?

Page 34 of 37
Most of the web applications, like ours, has such cases: Two users retrieve and modify a data on the page, then first
user saves the data a transaction and then second user modifies and saves the data in an another transaction. Here are 3
alternatives:
1. Last commit wins: Both updates are performed, the second user overwrites without seeing the first user changes and
without any error message
2. First commit wins: (Optimistic Locking) The update is performed, but second user gets error message, requiring
restart of the processes on the first users changes.

3. Merge conflicting update : The second user are prompted to merge changes.

Automatic Versioning

Hibernate provides automatic versioning for options 2 and 3, using a version field managed by hibernate.

Versioning with integer version

public class MyClass {


...
private int version;
...
}

<class name="MyClass">
<id ...>
<version name="version" column="VERSION" access="field">
...
</class>

Versioning with timestamp

public class MyClass {


...
private int lastModifyDataTime;
...
}

<class name="MyClass">
<id ...>
<timestamp name="lastModifyDataTime" column="LAST_MODIFIY_DATE_TIME" access="field">
...
</class>

Automatic versioning is handled by hibernate, you don’t need to update versions/timestamps.


Considering the example mentioned above, when second user saves, hibernate finds this user is working on the stale
data and throws StaleObjectException.
Page 35 of 37
You can catch this exception, and re-throw your own exception. By the way, if you’re using Hibernate with spring, this
exception is wrapped with HibernateOptimisticLockingFailureException.

One more point, you should be aware of that hibernate ignores the versioning when getting object and updating fields
and then version are in the same session.

Using stored procedures for querying

Hibernate3 provides support for queries via stored procedures and functions. Most of the following documentation is
equivalent for both. The stored procedure/function must return a resultset as the first out-parameter to be able to work
with Hibernate. An example of such a stored function in Oracle 9 and higher is as follows:
CREATE OR REPLACE FUNCTION selectAllEmployments
RETURN SYS_REFCURSOR
AS
st_cursor SYS_REFCURSOR;
BEGIN
OPEN st_cursor FOR
SELECT EMPLOYEE, EMPLOYER,
STARTDATE, ENDDATE,
REGIONCODE, EID, VALUE, CURRENCY
FROM EMPLOYMENT;
RETURN st_cursor;
END;
To use this query in Hibernate you need to map it via a named query.

<sql-query name="selectAllEmployees_SP" callable="true">


<return alias="emp" class="Employment">
<return-property name="employee" column="EMPLOYEE"/>
<return-property name="employer" column="EMPLOYER"/>
<return-property name="startDate" column="STARTDATE"/>
<return-property name="endDate" column="ENDDATE"/>
<return-property name="regionCode" column="REGIONCODE"/>
<return-property name="id" column="EID"/>
<return-property name="salary">
<return-column name="VALUE"/>
<return-column name="CURRENCY"/>
</return-property>
</return>
{ ? = call selectAllEmployments() }
</sql-query>
Stored procedures currently only return scalars and entities. <return-join> and <load-collection> are not supported.

Rules/limitations for using stored procedures

You cannot use stored procedures with Hibernate unless you follow some procedure/function rules. If they do not
follow those rules they are not usable with Hibernate. If you still want to use these procedures you have to execute

Page 36 of 37
them via session.connection(). The rules are different for each database, since database vendors have different stored
procedure semantics/syntax.

Stored procedure queries cannot be paged with setFirstResult()/setMaxResults().

The recommended call form is standard SQL92: { ? = call functionName(<parameters>) } or { ? = call


procedureName(<parameters>}. Native call syntax is not supported.

For Oracle the following rules apply:

A function must return a result set. The first parameter of a procedure must be an OUT that returns a result set. This is
done by using a SYS_REFCURSOR type in Oracle 9 or 10. In Oracle you need to define a REF CURSOR type. See
Oracle literature for further information.

Page 37 of 37

You might also like