An Introduction to Hibernate
By Mr.Subrahmanyabharathi Pendyala Tata Consultancy Services Ltd Hyderabad.
Agenda
What is Hibernate
Overview Features Benefits Examples Important Concepts Best Practices
Spring Integration
Benefits Example
What is Hibernate?
Popular Open Source Object/Relational Mapping (ORM) tool Transparent persistence for POJOs (Plain Old Java Objects) Core of JBoss CMP 2.0 impl.
Features
Mapping from Java classes to database tables (and from Java data types to SQL data types). Data query and retrieval facilities. Generates the SQL calls and relieves the developer from manual result set handling and object conversion Portable to all data bases Provides persistence for Plain Old Java Objects(POJO)
Features
Support for detached persistent objects Powerful yet Simple queries using HQL.
Why should you use it
EJB (2.x)
Developer has to write EJB QL for CMP or native SQL for BMP. Database dependent Doesnt support OO mapping concepts Developer may not able to write optimal query, less performance
Hibernate
Hibernate generates query called HQL Data base independent Supports OO concepts like, Inheritance and Polymorphic mappings HQL is gives optimal query and gives more performance
Why should you use it
EJB(2.x)
y EJB container is required to
Hibernate
y No specific container needed y Hibernate components are
run the EJB s y EJB s are distributed components y EJB s can be invoked remotely
not distributed y Can't be invoked remotely
Why Hibernate?
Retains natural object model (transparent) Minimizes Code Does not require a container Model is not tied to persistence implementation
What to do RDBs do well Work with large amounts of data
Work with sets of data
Searching, sorting
Sharing
Joining, aggregating Concurrency (Transactions) Many applications Constraints Transaction isolation
Integrity
What to do RDBs do badly
Modeling
No polymorphism Fine grained models are difficult Stored procedures. (arguable, I suppose)
Business logic
Distribution
Data is important
Even so, the relational model is important The data will be around much longer than the Java application
The Goal
Take advantage of those things that relational databases do well Without leaving the language of objects / classes
The Real Goal
Do less work Happy DBA
Sample OR Mapping file
<?xml version="1.0"?> <!DOCTYPE hibernate-mapping PUBLIC "-//Hibernate/Hibernate Mapping DTD 3.0//EN" "http://hibernate.sourceforge.net/hibernatemapping-3.0.dtd"> <hibernate-mapping>
<class name="events.Event" table="EVENTS"> <id name="id" column="EVENT_ID"> <generator class="native"/> </id> <property name="date" type="timestamp" column="EVENT_DATE"/> <property name="title"/> </class>
</hibernate-mapping>
How does it handle Database Connectivity
Hibernate configuration XML file <?xml version='1.0' encoding='utf-8'?> <!DOCTYPE hibernate-configuration PUBLIC "-//Hibernate/Hibernate Configuration DTD 3.0//EN" "http://hibernate.sourceforge.net/hibernateconfiguration-3.0.dtd"> <hibernate-configuration> <session-factory> <!-- Database connection settings --> <property name="connection.driver_class">org.hsqldb.j dbcDriver</property> <property
How does it handle database connectivity
<!-- SQL dialect --> <property name="dialect">org.hibernate.dialect.HSQLD ialect</property> <!-- Enable Hibernate's automatic session context management --> <property name="current_session_context_class">thre ad</property> <!-- Disable the second-level cache --> <property name="cache.provider_class">org.hibernate. cache.NoCacheProvider</property> <!-- Echo all executed SQL to stdout -->
Object/Relational Mapping
JavaObject
int id; String name; String getName() int getId() void setName(String) void setId(int)
SQL Table id [int] primary key, name [varchar(50)]
Magic Happens Here (O/R Mapper i.e. Hibernate)
Other ORM Solutions
Open
iBatis SQL Maps JDO
Commercial
TopLink
Hibernate's Goal
Remove 95% of common data persistence problems
Person.java
Hibernate Component Mapping Example
person.hbm l .xm
person table
Nam e.java
Hibernate Collection M apping w ith recursion and subclassing
Cat.java cat.hbm.xml
cats
table
OR Mapping Made easy
Visualize the object model in terms of relationships. Write the Java classes for each object in the model. Add relevant Xdoclet tag to the code at the appropriate places. Use the relevant ant targets in the ant script to generate the mapping XML files for OR mapping. If the script is intelligent enough, you can also create database schema
How to Relationships of Object Model
Microsoft Word Document
Sample Build Script
XML Document
How do you use it?
Act on your data model Query in SQL and/or HQL ... or using your object model
Auction Object Model
Persistent Class
Default Constructor Getters/Setters Collections use interface types Identifier property
public class AuctionItem { private Long _id; private Set _bids; private Bid _successfulBid private String _description; public Long getId() { return _id; } private void setId(Long id) { _id = id; } public String getDescription() { return _description; } public void setDescription(String desc) { _description=desc; } }
XML Mapping
<class name=AuctionItem table=AUCTION_ITEM> <id name=id column=ITEM_ID> <generator class=native/> </id> <property name=description column=DESCR/> <many-to-one name=successfulBid column=SUCCESSFUL_BID_ID/> <set name=bids cascade=all lazy=true> <key column=ITEM_ID/> <one-to-many class=Bid/> </set> </class>
Readable metadata Column/Table map Key Generation Collections Fetching Strategies
Working with Data
Retrieve an AuctionItem and change description
Session session = sessionFactory.openSession(); Transaction tx = s.beginTransaction(); AuctionItem item = (AuctionItem) session.get(ActionItem.class, itemId); item.setDescription(newDescription); tx.commit(); session.close();
Working with Data
Retrieve an AuctionItem and create a new persistent Bid
Bid bid = new Bid(); bid.setAmount(bidAmount); Session session = sf.openSession(); Transaction tx = session.beginTransaction(); AuctionItem item = (AuctionItem) session.get(ActionItem.class, itemId); bid.setItem(item); item.getBids().add(bid); tx.commit(); session.close();
Hibernate in code
Retrieve an AuctionItem and create a new persistent Bid
Bid bid = new Bid(); bid.setAmount(bidAmount); Session session = sf.openSession(); Transaction tx = session.beginTransaction(); AuctionItem item = (AuctionItem) session.get(ActionItem.class, itemId); bid.setItem(item); item.getBids().add(bid); tx.commit(); session.close();
Working with detached objects.
Retrieve an AuctionItem and create a new persistent Bid
Session session = sf.openSession(); Transaction tx = session.beginTransaction(); AuctionItem item = (AuctionItem) session.get(ActionItem.class, itemId); tx.commit(); session.close(); item.setDescription(newDescription); Session session2 = sf.openSession(); Transaction tx = session2.beginTransaction(); session2.update(item); tx.commit(); session2.close();
Lazy Fetching
AuctionItem item = (AuctionItem) session.get(ActionItem.class, itemId); SELECT FROM AUCTION_ITEM ITEM WHERE ITEM.ITEM_ID = ? Iterator iter = item.getBids().iterate(); SELECT FROM BID BID WHERE BID.ITEM_ID = ? item.getSuccessfulBid().getAmount(); SELECT FROM BID BID WHERE BID.BID_ID = ?
DTOs are Evil
Useless extra LOC Not objects (no behavior) Parallel class hierarchies smell Shotgun change smell Solution: detached object support
Detached Object Support
For applications using servlets + session beans You dont need to select a row when you only want to update it! You dont need DTOs anymore! You may serialize objects to the web tier, then serialize them back to the EJB tier in the next request Hibernate lets you selectively reassociate a subgraph! (essential for performance)
Detached Object Support
Step 1: Retrieve some objects in a session bean:
public List getItems() throws { return getSession() .createQuery(from AuctionItem item where item.type = :itemType)
Detached Object Support
Step 2: Collect user input in a servlet/action:
item.setDescription(newDescription);
Detached Object Support
Step 3: Make the changes persistent, back in the session bean:
public void updateItem(AuctionItem item) throws { getSession().update(item); }
Transitive Persistence
Session session = sf.openSession(); Transaction tx = session.beginTransaction(); AuctionItem item = (AuctionItem) session.get(ActionItem.class, itemId); tx.commit(); session.close(); Bid bid = new Bid(); bid.setAmount(bidAmount); bid.setItem(item); item.getBids().add(bid); Session session2 = sf.openSession(); Transaction tx = session2.beginTransaction(); session2.update(item); tx.commit(); session2.close();
The Big Problem
Detached objects + Transitive persistence! How do we distinguish between newly instantiated objects and detached objects that are already persistent in the database?
The Big Problem (solution)
1.
Version property (if there is one) Identifier value e.g. unsaved-value=0 (only works for generated surrogate keys, not for natural keys in legacy data) Write your own strategy, implement Interceptor.isUnsaved()
2.
3.
Benefits
Metadata controlled persistence Transparent - working with the model, not the data access technology Pooling, Caching, Transactions can all be handled outside of our code
Integrating Spring and Hibernate
Spring and Hibernate
Benefits Examples
Benefits
Resource Management
IoC / AOP Session Management
Extended Transaction Support
JTA and/or JDBC Flexible Transaction Demarcation
Programmatic Declarative (Spring's XML config)
HibernateTemplate
Simplifies Hibernate API
Spring IoC
Session
setSession()
DAO
save()
POJO
Spring Interceptors (AOP)
Business Logic
getCatById()
Interceptor
DAO
save(Cat)
Session
Spring Framework
Springs HibernateTemplate
Hibernate Only:
public User getUserByEmailAddress(final String email) { try { Session session = sessionFactory.openSession(); List list = session.find( "from User user where user.email=?", email, Hibernate.STRING); return (User) list.get(0); } finally { session.close(); } }
HibernateTemplate:
public User getUserByEmailAddress(final String email) { List list = getHibernateTemplate().find( "from User user where user.email=?", email, Hibernate.STRING); return (User) list.get(0); }
Some Important Concepts
Lazy Loading --Getting the objects when needed
Eager Loading Getting it the first time when you hit the database Difference between load and get methods Load() --- Retrieves the objects from the Persistence Context , only if not available, database will be hit. Get() Retrieves from database. Fetch Strategies Inheritance strategies Separate tables (implicit polymorphism) Ideally not preferred. Redundancy creeps in. Table Per class hierarchy (with discriminator column) Use it when data size is small Normalized tables ( Good when working with large data)
Some Important Concepts
Transient Persistence (Persistence works similarly for transient , detached , attached objects) Detached Object support Optimistic locking ( through version fields preferably integers) Pessimistic locking ( using session.lock() method) Batch operations and best practices Sub selects ,Pre defined batch size Persistence Context ( Maintains cache of retrieved objects) SessionFactory( Thread safe) & Session (Not thread safe)
Object states and lifecycle Transient, Persistent, Detached, Removed
Important Links
http://www.hibernate.org http://www.springframework.org
Parts of this presentation come from documentation and presentations on the hibernate.org website:
http://www.hibernate.org/hib_docs/reference/en/pdf/hibernate_reference.pdf - Manual http://www.hibernate.org/hib_docs/online/jaoo_presentation/HibernateJAOO.ppt - Presentation by Gavin King http://www.hibernate.org/200.html - Road Map
Tutorials: http://raibledesigns.com/wiki/Wiki.jsp?page=CreateDAO http://raibledesigns.com/wiki/Wiki.jsp?page=AppFuseQuickStart
THANK YOU