Professional Documents
Culture Documents
Configuration Layer
Application Layer
Callback Layer
(Interceptor, Validatable, Lifecycle)
Persistence Layer
Session, Transaction, Query,
SessionFactory
Dialect JDBC
Application Domain Objects (POJO)
Application
Database
Hibernate Interfaces
As described earlier the major interfaces of concern
in hibernate are
Session
SessionFactory
Configuration
Transaction
Query
Callback
Types
Extension
Session Interface
Primary interface used by application when
interacting with hibernate
Found in the package “org.hibernate”
Light weight interface that acts as a persistence
manager
It is not thread safe and so should be used one per
thread
Represents one unit of work. In web invocation terms,
can be mapped to one client request
The basic level of object cache in hibernate
SessionFactory
Acts as Factory to the Session objects
SessionFactory used across the application
One SessionFactory per database
Can provide second level of cache for objects
across sessions
Configuration
Used for configuring the hibernate
Provides access to the configured
SessionFactory
Transaction
An optional API, applications can use its own
transaction infrastructure if desired
Provides abstraction over lower level transaction
implementation either via JDBC or JTA
Query
Used for querying database to retrieve objects
Provides way to set query parameters and limit result
size
Comes with a Criteria interface to filter search
Callback
Allows applications to keep track of the events
happening in hibernate
Interceptor can be used to react to lifecycle
events
Types
Hibernate Types map to the java types of the data stored
in DB
UserType and CompositeUserType can be used to add
domain specific types to hibernate
Extension
Allows extending hibernate functionalities
Commonly used extension interfaces are
IdentifierGenerator and Dialect
Lifecycle of persistent object
The application domain objects (POJO) are
the persistent objects
The persistence object can be in one of the
three states
Transient
Persistent
Detached
Lifecycle of persistent object
new
Transient
save()
get() saveOr
load() Update delete()
find() () Garbage
iterate() Persistent collected
evict() update()
close() saveOrUpd
clear() ate()
lock()
Detached
Transient Object
Any application domain object created using a new()
operator is a transient object and as such a plain java
object
Any state in such an object is not associated with any
database table row
If such an object is destroyed without becoming
persistent, then no data held by the object is stored in
the DB
For an object to move from transient state to
persistent state requires a call to save() method of
the persistence manager
Persistent Object
An object with its database identifier set is a
persistent object
Persistent object is always part of a session
and is transactional
A persistent object can be created by calling
save() on the Persistence manager
Persistent object might be an instance
retrieved from DB using a query
Persistent Object
Persistent objects participate in transactions and its
state is synchronized with the database at the end of
transaction
When transaction is committed, Persistent object is
synchronized with DB using INSERT, UPDATE or
DELETE
Persistent object may also be synchronized with DB
before execution of a query to get latest data from DB
into memory
Detached Object
A domain object is persistent only in the scope of the
session in which it was created
If the session is closed using Session.close() then all
persistent objects that are still referenced after close()
are in detached state
They are no longer associated with any transaction
and will not be synchronized with the database
The data contained in such objects may not be the
latest.
Object Identity
In Java, objects are often compared for
equality using object identity (a==b)
A persistent object may also require
comparison of its database identifier, to
establish identity.
Concept of transient, persistent and detached
objects provides different scopes for objects
within which there identities may differ
Object Identity
Hibernate supports Transaction-Identity scope
If a persistent object is accessed multiple times within
a same transaction, then hibernate ensures that the
same instance is always returned
This ensures that within a transaction, application
works on the same data
Once a transaction is committed and a session is
closed, the detached object is no longer in the
transactional scope
Object Identity
Equality between to persistent objects can be
best established by proper implementation of
equals() method in the domain class
Typical implementation of equals() method will
be as follows
Table Message
CREATE TABLE Message (
Message_ID INTEGER UNSIGNED NOT NULL
AUTO_INCREMENT,
NextMessageID INTEGER UNSIGNED NULL,
text VARCHAR(20) NULL,
PRIMARY KEY(Message_ID),
INDEX Message_FKIndex1(NextMessageID)
);
Hello World
Create a domain class Message
package com.sample.hibernate.model;
public class Message {
private Long id;
private String message;
private Message(){}
import com.sample.hibernate.model.Message;
public class MessageDAO {
session.save(message);
tx.commit();
session.close();
Object associations
In the world of OOP the relations between entities are
more commonly implemented using associations that
can be
Composition
Inheritance
One-to-One relations using foreign key
The relational data can have a one-to-one
relationship as can be seen between a person and
his/her address
One-to-One relations using foreign key
Person.hbm.xml
<many-to-one name="billingAddress"
class="com.sample.hibernate.mode.Address"
column="Address_id"
cascade="save-update"/>
One-to-One relations using foreign
key-Bidirectional
In the above example, there is only one way navigation from
Person to Address.
If we would like to go back to person instance from Address,
then there should be a reference to Person in Address class,
which will be mapped as follows
Address.hbm.xml
<one-to-one name=“person"
class="com.sample.hibernate.mode.
Person"
property-ref=“billingAddress"/>
This will ensure that the Address instance will hold reference to
its appropriate Person instance so that bi-directional navigation
can be achieved
One-to-One relations using primary
key
The one-to-one relation can also be established through
primary key association
The primary key will also act as a foreign key in this case
One-to-One relations using primary
key
In this case it must be ensured that the newly created Address
objects have the same key as the Person for which it is created
The mappings in this case will be
Person.hbm.xml
<one-to-one name="billingAddress"
class="com.sample.hibernate.mode.Address"
cascade="save-update"/>
Address.hbm.xml
<one-to-one name=“person"
class="com.sample.hibernate.mode.Person"
constrained=“true"/>
Constrained attribute tells hibernate that the Address has a foreign key
constraint on its primary key and it refers to the Person primary key
One-to-One relations using primary
key
To ensure that newly saved Address instances are assigned
the same primary key as that of the person, a special
identifier-generator needs to be used
Address.hbm.xml
<class name="com.sample.hibernate.mode.Address"
table="Address">
<id name="id" column="Person_id" >
<generator class="foreign">
<param
name="property">person</param>
</generator>
</id>
The property “person” of the new Address object is used to get the
identifier which is assigned to the Address identifier
One-to-Many relations unidirectional
The item table in an auction will have multiple bids
placed on it, and will have a one to many relation
One-to-Many relations unidirectional
For unidirectional navigation, the item class will hold a collection
of bids
The relationship will be mapped using the <set> element
Item.hbm.xml
Bid.hbm.xml
<many-to-one name=“item"
column="Item_ID“
class=“Item”
not-null=“true"/>
Many-to-Many relations unidirectional
A many to many relation should ideally make use
of a link table
The link table will have foreign keys to the primary
keys of the original table
Many-to-Many relations unidirectional
The category class in this case will hold reference
to the Item in the form of collection of value types
Category.hbm.xml
<set name="items"
table="CATEGORY_ITEM"
lazy="true"
cascade="save-update“>
<key column="category_id"/>
<many-to-many class="Item"
column="Item_ID"/>
</set>
Many-to-Many relations bidirectional
Item class holds reference to categories
Item.hbm.xml
<set name=“categories"
table="CATEGORY_ITEM"
lazy="true“
inverse=“true”
cascade="save-update"
<key column=“Item_ID"/>
<many-to-many class=“Category"
column=“Category_ID"/>
</set>
BillingDetails
Owner:String
number:String
Created:Date
CreditCard BankAccount
Type:int
expMonth:String Name:String
expYr:String Swift:string
Mapping inheritance
One of the strategies that can be applied is Table
per concrete class
In this case, the user name and details are same,
only the type specific details differ
<joined-subclass name="CreditCard"
table="CreditCardDetails">
<key column="Billing_Details_Id"/>
<property name="cctype" column="cctype"/>
</joined-subclass>
</class>
Basic Queries
Queries
Queries are most important for writing good
data access code
Hibernate provides extensive support for
querying using its Query interface
Queries are in terms of classes and
properties and not tables and columns
Hibernate also supports execution of native
SQL queries
Queries
Queries can be created on a session
Query hqlQuery = session.createQuery(“from
Person”);
Queries support pagination by limiting results
Query query = session.createQuery(“from
User”);
Query.setFirstResult(0);
Query.setMaxResults(10);
Queries
Queries support criteria for filtering searches
based on criteria
Session.createCriteria(Category.class).add(Ex
pression.like(“name”, “Laptop%”));
List() method executes the created query and
returns the results as a list
List result = session.createQuery(“from
User”).list();
Named Queries
Named queries help in avoiding HQL queries
to be located within Java files
The queries to be used in an application can
be externalized in an XML mapping file
The desired query can be referred to by the
name
Named Queries
getNamedQuery() method obtains a Query
instance from a named query
session.getNamedQuery("findItemsByDesc
ription").
setString("description", description).list();
<query
name="findItemsByDescription"><![CDATA
[from Item item where item.description like
:description]]>
</query>
Session.createCriteria(User.class).
add(Expression.eq(“address.city”,”city”));
Association
A fetch join can be used to specify that an
association should be eagerly fetched
Session.createCriteria(Item.class).
setFetchMode(“bids”, FetchMode.EAGER).
list()
Theta Style Join
Theta style joins are to perform joins between
two un-associated classes
Session.createSQLQuery(sql).
addEntity(Address.class);
Handling associations
When an entity has a many-to-one relation
with another, then it is required to return the
association or else a column not found error
will be returned
A * notation will return the association
String sql = "select * from appuser";
ses.createSQLQuery(sql).
addEntity(Appuser.class).
list();
Returning Non-Managed entities
SQL can be used to return non-managed entities
The entity instances returned may not reflect the
latest values over a session
String sql = "select lane, city from address
where city like ?";
ses.createSQLQuery(sql)
.setResultTransformer(Transformers.
aliasToBean(Address.class)).
setString(0, name)
.list();
Named SQL Query
SQL queries can be written externally and accessed in the code
Named queries allow more flexibility to modify queries
<sql-query name="cityQuery">
import java.math.BigDecimal;
import java.math.BigDecimal;
Session
Cache
Query Cache
Strategy
Cache Provider
<class name="BillingDetails"
table="Billing_Details">
<cache usage="read-write"/>