object/relational mapping with hibernate
DESCRIPTION
Object/Relational Mapping with Hibernate. Practical ORM. Who is this guy?. Gavin King [email protected]. “Modern” ORM Solutions. Transparent Persistence (POJO/JavaBeans) Persistent/transient instances Automatic Dirty Checking Transitive Persistence Lazy Fetching Outer Join Fetching - PowerPoint PPT PresentationTRANSCRIPT
![Page 1: Object/Relational Mapping with Hibernate](https://reader035.vdocument.in/reader035/viewer/2022070409/56814499550346895db13f9f/html5/thumbnails/1.jpg)
Object/Relational Mapping with Hibernate
Practical ORM
![Page 2: Object/Relational Mapping with Hibernate](https://reader035.vdocument.in/reader035/viewer/2022070409/56814499550346895db13f9f/html5/thumbnails/2.jpg)
Who is this guy? Gavin King [email protected]
![Page 3: Object/Relational Mapping with Hibernate](https://reader035.vdocument.in/reader035/viewer/2022070409/56814499550346895db13f9f/html5/thumbnails/3.jpg)
“Modern” ORM Solutions Transparent Persistence (POJO/JavaBeans) Persistent/transient instances Automatic Dirty Checking Transitive Persistence Lazy Fetching Outer Join Fetching Runtime SQL Generation Three Basic Inheritance Mapping
Strategies
![Page 4: Object/Relational Mapping with Hibernate](https://reader035.vdocument.in/reader035/viewer/2022070409/56814499550346895db13f9f/html5/thumbnails/4.jpg)
Why? Natural programming model Minimize LOC Code can be run and/or tested outside the
“container” Classes may be reused in “nonpersistent”
context Minimize database access with smart fetching
strategies Opportunities for aggressive caching Structural mapping more robust when
object/data model changes
![Page 5: Object/Relational Mapping with Hibernate](https://reader035.vdocument.in/reader035/viewer/2022070409/56814499550346895db13f9f/html5/thumbnails/5.jpg)
Entity Beans? Transparent Persistence Persistent/transient instances Automatic Dirty Checking Transitive Persistence Lazy Fetching Outer Join Fetching Runtime SQL Generation Three Basic Inheritance Mapping
Strategies
![Page 6: Object/Relational Mapping with Hibernate](https://reader035.vdocument.in/reader035/viewer/2022070409/56814499550346895db13f9f/html5/thumbnails/6.jpg)
What do RDBs do well? Work with large amounts of data
Searching, sorting Work with sets of data
Joining, aggregating Sharing
Concurrency (Transactions) Many applications
Integrity Constraints Transaction isolation
![Page 7: Object/Relational Mapping with Hibernate](https://reader035.vdocument.in/reader035/viewer/2022070409/56814499550346895db13f9f/html5/thumbnails/7.jpg)
What do RDBs do badly? Modeling
No polymorphism Fine grained models are difficult
Business logic Stored procedures kinda suck
Distribution (arguable, I suppose)
![Page 8: Object/Relational Mapping with Hibernate](https://reader035.vdocument.in/reader035/viewer/2022070409/56814499550346895db13f9f/html5/thumbnails/8.jpg)
Data is important
Even so, the relational model is important…
The data will be around much longer than the Java application!
![Page 9: Object/Relational Mapping with Hibernate](https://reader035.vdocument.in/reader035/viewer/2022070409/56814499550346895db13f9f/html5/thumbnails/9.jpg)
The Goal Take advantage of those things that
relational databases do well Without leaving the language of
objects / classes
![Page 10: Object/Relational Mapping with Hibernate](https://reader035.vdocument.in/reader035/viewer/2022070409/56814499550346895db13f9f/html5/thumbnails/10.jpg)
The Real Goal Do less work Happy DBA
![Page 11: Object/Relational Mapping with Hibernate](https://reader035.vdocument.in/reader035/viewer/2022070409/56814499550346895db13f9f/html5/thumbnails/11.jpg)
Hibernate Opensource (LGPL) Mature Popular (13 000 downloads/month) Custom API Will be core of JBoss CMP 2.0 engine
![Page 12: Object/Relational Mapping with Hibernate](https://reader035.vdocument.in/reader035/viewer/2022070409/56814499550346895db13f9f/html5/thumbnails/12.jpg)
Hibernate Persistence for JavaBeans Support for very fine-grained, richly
typed object models Powerful queries Support for detached persistent
objects
![Page 13: Object/Relational Mapping with Hibernate](https://reader035.vdocument.in/reader035/viewer/2022070409/56814499550346895db13f9f/html5/thumbnails/13.jpg)
Auction Object Model
![Page 14: Object/Relational Mapping with Hibernate](https://reader035.vdocument.in/reader035/viewer/2022070409/56814499550346895db13f9f/html5/thumbnails/14.jpg)
Persistent Class Default
constructor Get/set pairs Collection
property is an interface type
Identifier property
public class AuctionItem {private Long _id;private Set _bids;private Bid _successfulBidprivate 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;}…
}
![Page 15: Object/Relational Mapping with Hibernate](https://reader035.vdocument.in/reader035/viewer/2022070409/56814499550346895db13f9f/html5/thumbnails/15.jpg)
XML Mapping Readable
metadata Column /
table mappings
Surrogate key generation strategy
Collection metadata
Fetching strategies
<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>
![Page 16: Object/Relational Mapping with Hibernate](https://reader035.vdocument.in/reader035/viewer/2022070409/56814499550346895db13f9f/html5/thumbnails/16.jpg)
Dirty CheckingRetrieve 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();
![Page 17: Object/Relational Mapping with Hibernate](https://reader035.vdocument.in/reader035/viewer/2022070409/56814499550346895db13f9f/html5/thumbnails/17.jpg)
Transitive PersistenceRetrieve 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();
![Page 18: Object/Relational Mapping with Hibernate](https://reader035.vdocument.in/reader035/viewer/2022070409/56814499550346895db13f9f/html5/thumbnails/18.jpg)
DetachmentRetrieve 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();
![Page 19: Object/Relational Mapping with Hibernate](https://reader035.vdocument.in/reader035/viewer/2022070409/56814499550346895db13f9f/html5/thumbnails/19.jpg)
Optimizing Data Access Lazy Fetching Eager (Outer Join) Fetching Batch Fetching
![Page 20: Object/Relational Mapping with Hibernate](https://reader035.vdocument.in/reader035/viewer/2022070409/56814499550346895db13f9f/html5/thumbnails/20.jpg)
Transparent Lazy FetchingAuctionItem 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 = ?
![Page 21: Object/Relational Mapping with Hibernate](https://reader035.vdocument.in/reader035/viewer/2022070409/56814499550346895db13f9f/html5/thumbnails/21.jpg)
Outer Join Fetching<class name=“AuctionItem” table=“AUCTION_ITEM”>
<id name=“id” column=“ITEM_ID”>
<generator class=“native”/>
</id>
<property name=“description” column=“DESC”/>
<many-to-one name=“successfulBid”
outer-join=“true”
column=“SUCCESSFUL_BID_ID”/>
<set name=“bids”
cascade=“all”
outer-join=“true”>
<key column=“ITEM_ID”/>
<one-to-many class=“Bid”/>
</set>
</class>
![Page 22: Object/Relational Mapping with Hibernate](https://reader035.vdocument.in/reader035/viewer/2022070409/56814499550346895db13f9f/html5/thumbnails/22.jpg)
Outer Join FetchingAuctionItem item = (AuctionItem) s.get(ActionItem.class, itemId);
SELECT …
FROM AUCTION_ITEM ITEM
LEFT OUTER JOIN BID BID1 ON BID1.ITEM_ID = ITEM.ITEM_ID
LEFT OUTER JOIN BID BID2 ON BID2.BID_ID = ITEM.SUCCESSFUL_BID
WHERE ITEM.ITEM_ID = ?
![Page 23: Object/Relational Mapping with Hibernate](https://reader035.vdocument.in/reader035/viewer/2022070409/56814499550346895db13f9f/html5/thumbnails/23.jpg)
Optimizing Data Access Minimize row reads Minimize database roundtrips (Much less important) Minimize
column reads
![Page 24: Object/Relational Mapping with Hibernate](https://reader035.vdocument.in/reader035/viewer/2022070409/56814499550346895db13f9f/html5/thumbnails/24.jpg)
Optimizing Data Access Minimize row reads
Use lazy fetching Minimize database roundtrips
Use outer join fetching (Much less important) Minimize
column reads Come back to this one later…
![Page 25: Object/Relational Mapping with Hibernate](https://reader035.vdocument.in/reader035/viewer/2022070409/56814499550346895db13f9f/html5/thumbnails/25.jpg)
Optimizing Data Access Minimize row reads
Use lazy fetching• N+1 Selects Problem (too many
roundtrips)
Minimize database roundtrips Use outer join fetching
• Cartesian Product Problem (huge result set)
![Page 26: Object/Relational Mapping with Hibernate](https://reader035.vdocument.in/reader035/viewer/2022070409/56814499550346895db13f9f/html5/thumbnails/26.jpg)
Optimizing Data Access
Solution: Runtime Fetch Strategies1. Say what objects you need2. Navigate the object graph
![Page 27: Object/Relational Mapping with Hibernate](https://reader035.vdocument.in/reader035/viewer/2022070409/56814499550346895db13f9f/html5/thumbnails/27.jpg)
Hibernate Query Options Hibernate Query Language (HQL)
“Minimal” OO dialect of ANSI SQL Criteria Queries
Extensible framework for expressing query criteria as objects
Includes “query by example” Native SQL Queries
![Page 28: Object/Relational Mapping with Hibernate](https://reader035.vdocument.in/reader035/viewer/2022070409/56814499550346895db13f9f/html5/thumbnails/28.jpg)
Hibernate Query Language Make SQL be object oriented
Classes and properties instead of tables and columns Polymorphism Associations Much less verbose than SQL
Full support for relational operations Inner/outer/full joins, cartesian products Projection Aggregation (max, avg) and grouping Ordering Subqueries SQL function calls
![Page 29: Object/Relational Mapping with Hibernate](https://reader035.vdocument.in/reader035/viewer/2022070409/56814499550346895db13f9f/html5/thumbnails/29.jpg)
Hibernate Query Language HQL is a language for talking about “sets of
objects” It unifies relational operations with object models
![Page 30: Object/Relational Mapping with Hibernate](https://reader035.vdocument.in/reader035/viewer/2022070409/56814499550346895db13f9f/html5/thumbnails/30.jpg)
Hibernate Query Language
Simplest HQL Query:
from AuctionItem
i.e. get all the AuctionItems:
List allAuctions = session.createQuery(“from AuctionItem”)
.list();
![Page 31: Object/Relational Mapping with Hibernate](https://reader035.vdocument.in/reader035/viewer/2022070409/56814499550346895db13f9f/html5/thumbnails/31.jpg)
Hibernate Query LanguageMore realistic example:
select itemfrom AuctionItem item
join item.bids bidwhere item.description like ‘hib%’
and bid.amount > 100
i.e. get all the AuctionItems with a Bid worth > 100 and description that begins with “hib”
![Page 32: Object/Relational Mapping with Hibernate](https://reader035.vdocument.in/reader035/viewer/2022070409/56814499550346895db13f9f/html5/thumbnails/32.jpg)
Hibernate Query Language
Projection:
select item.description, bid.amount
from AuctionItem item
join item.bids bid
where bid.amount > 100
order by bid.amount desc
i.e. get the description and amount for all the AuctionItems with a Bid worth > 100
![Page 33: Object/Relational Mapping with Hibernate](https://reader035.vdocument.in/reader035/viewer/2022070409/56814499550346895db13f9f/html5/thumbnails/33.jpg)
Hibernate Query Language
Aggregation:
select max(bid.amount), count(bid)
from AuctionItem item
left join item.bids bid
group by item.type
order by max(bid.amount)
![Page 34: Object/Relational Mapping with Hibernate](https://reader035.vdocument.in/reader035/viewer/2022070409/56814499550346895db13f9f/html5/thumbnails/34.jpg)
Hibernate Query LanguageRuntime fetch strategies:
from AuctionItem itemleft join fetch item.bidsjoin fetch item.successfulBid
where item.id = 12
AuctionItem item = session.createQuery(…)
.uniqueResult(); //associations already fetcheditem.getBids().iterator();item.getSuccessfulBid().getAmount();
![Page 35: Object/Relational Mapping with Hibernate](https://reader035.vdocument.in/reader035/viewer/2022070409/56814499550346895db13f9f/html5/thumbnails/35.jpg)
Criteria QueriesList auctionItems =
session.createCriteria(AuctionItem.class)
.setFetchMode(“bids”, FetchMode.EAGER)
.add( Expression.like(“description”, description) )
.createCriteria(“successfulBid”)
.add( Expression.gt(“amount”, minAmount) )
.list();
Equivalent HQL:
from AuctionItem item
left join fetch item.bids
where item.description like :description
and item.successfulbid.amount > :minAmount
![Page 36: Object/Relational Mapping with Hibernate](https://reader035.vdocument.in/reader035/viewer/2022070409/56814499550346895db13f9f/html5/thumbnails/36.jpg)
Example QueriesAuctionItem item = new AuctionItem();item.setDescription(“hib”);Bid bid = new Bid();bid.setAmount(1.0);List auctionItems =
session.createCriteria(AuctionItem.class).add( Example.create(item).enableLike(MatchMode.START) ).createCriteria(“bids”)
.add( Example.create(bid) ).list();
Equivalent HQL:
from AuctionItem itemjoin item.bids bid
where item.description like ‘hib%’and bid.amount > 1.0
![Page 37: Object/Relational Mapping with Hibernate](https://reader035.vdocument.in/reader035/viewer/2022070409/56814499550346895db13f9f/html5/thumbnails/37.jpg)
Fine-grained Persistence “More classes than tables” Fine-grained object models are good
Greater code reuse More typesafe Better encapsulation
![Page 38: Object/Relational Mapping with Hibernate](https://reader035.vdocument.in/reader035/viewer/2022070409/56814499550346895db13f9f/html5/thumbnails/38.jpg)
Components Address class street, city, postCode properties STREET, CITY, POST_CODE columns of
the PERSON and ORGANIZATION tables Mutable class
![Page 39: Object/Relational Mapping with Hibernate](https://reader035.vdocument.in/reader035/viewer/2022070409/56814499550346895db13f9f/html5/thumbnails/39.jpg)
Components<class name=“Person” table=“PERSON”>
…
<component name=“address”>
<property name=“street” column=“STREET”/>
<property name=“city” column=“CITY”/>
<property name=“postCode” column=“POST_CODE”/>
</component>
</class>
![Page 40: Object/Relational Mapping with Hibernate](https://reader035.vdocument.in/reader035/viewer/2022070409/56814499550346895db13f9f/html5/thumbnails/40.jpg)
Custom Types MonetoryAmount class Used by lots of other classes Maps to XXX_AMOUNT and XXX_CURRENCY columns
Performs currency conversions (behaviour!)
Might be mutable or immutable
![Page 41: Object/Relational Mapping with Hibernate](https://reader035.vdocument.in/reader035/viewer/2022070409/56814499550346895db13f9f/html5/thumbnails/41.jpg)
Custom Types<class name=“Bid” table=“BID”>
…
<property name=“amount” type=“MonetoryAmountUserType”>
<column name=“AMOUNT”/>
<column name=“CURRENCY”/>
</property>
</class>
We still have to write the MonetoryAmountUserType class!
![Page 42: Object/Relational Mapping with Hibernate](https://reader035.vdocument.in/reader035/viewer/2022070409/56814499550346895db13f9f/html5/thumbnails/42.jpg)
DTOs are Evil “Useless” extra LOC Not objects (no behavior) Parallel class hierarchies smell Shotgun change smell
Solution: detached object support
![Page 43: Object/Relational Mapping with Hibernate](https://reader035.vdocument.in/reader035/viewer/2022070409/56814499550346895db13f9f/html5/thumbnails/43.jpg)
Detached Object Support For applications using servlets + session
beans You don’t need to select a row when you
only want to update it! You don’t 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)
![Page 44: Object/Relational Mapping with Hibernate](https://reader035.vdocument.in/reader035/viewer/2022070409/56814499550346895db13f9f/html5/thumbnails/44.jpg)
Detached Object SupportStep 1: Retrieve some objects in a session bean:
public List getItems() throws … {
return getSession()
.createQuery(“from AuctionItem item where item.type = :itemType”)
.setParameter(“itemType”, itemType)
.list();
}
![Page 45: Object/Relational Mapping with Hibernate](https://reader035.vdocument.in/reader035/viewer/2022070409/56814499550346895db13f9f/html5/thumbnails/45.jpg)
Detached Object SupportStep 2: Collect user input in a servlet/action:
item.setDescription(newDescription);
![Page 46: Object/Relational Mapping with Hibernate](https://reader035.vdocument.in/reader035/viewer/2022070409/56814499550346895db13f9f/html5/thumbnails/46.jpg)
Detached Object SupportStep 3: Make the changes persistent, back in the
session bean:
public void updateItem(AuctionItem item) throws … {
getSession().update(item);
}
![Page 47: Object/Relational Mapping with Hibernate](https://reader035.vdocument.in/reader035/viewer/2022070409/56814499550346895db13f9f/html5/thumbnails/47.jpg)
Detached Object SupportEven 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();
![Page 48: Object/Relational Mapping with Hibernate](https://reader035.vdocument.in/reader035/viewer/2022070409/56814499550346895db13f9f/html5/thumbnails/48.jpg)
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?
![Page 49: Object/Relational Mapping with Hibernate](https://reader035.vdocument.in/reader035/viewer/2022070409/56814499550346895db13f9f/html5/thumbnails/49.jpg)
The Big Problem (solution)1. Version property (if there is one)2. Identifier value e.g. unsaved-value=“0” (only
works for generated surrogate keys, not for natural keys in legacy data)
3. Write your own strategy, implement Interceptor.isUnsaved()
![Page 50: Object/Relational Mapping with Hibernate](https://reader035.vdocument.in/reader035/viewer/2022070409/56814499550346895db13f9f/html5/thumbnails/50.jpg)
Hibernate Info http://hibernate.org Hibernate in Action (Manning, 2004) Tool support
http://xdoclet.sf.net http://boss.bekk.no/boss/middlegen http://www.andromda.org/