Hibernate

treeexcellentSoftware and s/w Development

Dec 13, 2013 (3 years and 8 months ago)

78 views

© by Nicus for SDA
Hibernate
Hibernate
Object/Relational persistence
Based on:


Hibernate Introduction

(Atlanta Java User Group, January 2004)


Hibernate in Action

(C.Bauer, G.King - Manning Publ)
© by Nicus for SDA
Agenda
Agenda
Part 1: Hibernate features

Hibernate architecture

Entity persistence

Entity retrieving
Part 2: Details and pitfalls
© by Nicus for SDA
RDBMS – Java (OOP) mismatch
RDBMS – Java (OOP) mismatch
Structural
mismatch

Java types vs. SQL datatypes

Type inheritance

Relationship vs. Collection semantics
Behavioral
aspects

Java Obj. identity, equality vs. PKs

Polymorphism

Joining Tables vs. navigating Associations
© by Nicus for SDA
Hibernate (main) feartures
Hibernate (main) feartures

Persistence for
POJO
s (
Plain Old Java Objects
)
(JavaBeans)

Flexible, declarative (XML)
O-R mapping

Mapping support for
fine-grained
object model

Inheritance
mapping, multiple strategies

Dual layer cache
(transaction level, JVM/Cluster level)

Dual query interface: HQL, Criteria API
(+ direct SQL)

Support for
detached objects
:
DTOs

...
© by Nicus for SDA
Hibernate framework
Hibernate framework
architecture
architecture
create
create

use
use
Co
nfigurati
on
Sync'ed
© by Nicus for SDA
Architecture (2)
Architecture (2)
SessionFactory

Creates
Session

Heavyweight

Thread-safe

One instance per application, per database

Creates
Session
Session

Persistence manager

Lightweight

Serializable
(may be put in HttpSession)

Encapsulate JDBC Connection

NOT thread-safe!

Manage 1
st
level persistent entity cache
© by Nicus for SDA
Architecture (3)
Architecture (3)
Transaction

Transparently encapsulate transaction

JDBC or JTA support

Tied at a
Session
Query

HQL query handler
Criteria

O.O. query API
© by Nicus for SDA
Main components scopes
Main components scopes
(suggested)
(suggested)
Application scope
HttpRequest scope
(controller + view!)
© by Nicus for SDA
Transparent Persistence
Transparent Persistence

Any class
can be a
Persistent class
:
No Interface to be implemented
No persistent superclass to be extended

No pre-compile source code modification

No post-compile bytecode modification

No (less) dependency on persistence layer

Persistent classes can be used in other contexts

Transparent Persistence
¹
Persistence by Reachability
© by Nicus for SDA
Persistent Classes:
Persistent Classes:
requirements & suggestions
requirements & suggestions

JavaBean
specs.

Accessors methods for properties
(not strictly req., accessors may be not-public)

No-arg constructor

Collection properties must be
java.util.*

interfaces
(
List
,
Set
,
Map
... array,
Collection
)

OID may be auto-implemented
Suggested...

Scaffold code,
grouping operations
(for managing association and collections)

Synthetic
ID
s, using
Object
(nullable):
Long
, not
long
(
strongly
suggested!)

Serializable
© by Nicus for SDA
Object model example
Object model example
© by Nicus for SDA
Automatic Dirty Checking
Automatic Dirty Checking
Retrieve an
AuctionItem,
change
description

and update:
Session session = sessionFactory.openSession();
Transaction tx = session.beginTransaction();
AuctionItem item =
(AuctionItem) session.get(AuctionItem.class, itemId);
item.setDescription(newDescription);
tx.commit();
session.close();

Dirty” object in Session are automatically detected
and updated on session close
flush
© by Nicus for SDA
Transitive Persistence
Transitive Persistence
Retrieve an
AuctionItem,
create a new
Bid
,
add to
AuctionItem
and persist everithing
Bid bid = new Bid();
bid.setAmount(bidAmount);
Session session = sessionFactory.openSession();
Transaction tx = session.beginTransaction();
AuctionItem item =
(AuctionItem) session.get(AuctionItem.class, itemId);
bid.setItem(item);
item.getBids().add(bid);
tx.commit();
session.close();
Application-managed
associations!
Associated objects
(may) be automatically persisted (
cascade
)
© by Nicus for SDA
Detached objects
Detached objects
Retrieve an
AuctionItem
and
change
description
in indipendent HttpRequests
Session session = sessionFactory.openSession();
Transaction tx = session.beginTransaction();
AuctionItem item =
(AuctionItem) session.get(AuctionItem.class, itemId);
tx.commit();
session.close();
...
item.setDescription(newDescription);
...
Session session2 = sessionFactory.openSession();
Transaction tx = session.beginTransaction();
session2.update(item);
tx.commit();
session2.close();
request 1
re
quest 2
request 3
Detached object
(out of Session)
Reattach object
(to Session)
© by Nicus for SDA
Detached objects (2)
Detached objects (2)

Persistent object “
lives
” as normal Java objects
when
detached
from Session

Detached object may be freely modified

Automatic dirty check and update after reattaching
to a (new) Session,
even with
transitive persistence

(cascade, configurable)

(Automatic optimistic locking, by versioning)
Detached entities may
replace DTOs
© by Nicus for SDA
Persistent Entity lifecycle
Persistent Entity lifecycle
garbage
Transient
Persistent
Detached
new
get()
load()
find()
...
save()
saveOrUpdate()
delete()
evict()
close()
clear()
update()
saveOrUpdate()
lock()
garbage
sync
© by Nicus for SDA
Persistence lifecycle
Persistence lifecycle
management methods
management methods

save()
make an object
persistent
(attached to a
Session
and automatically dirty-checked)
®
a
ctual DB save (
insert
) on
Session
flush

update()
reattach a detached object to a new
Session
.
®

DB
update
happens on
Session
flush

delete()
make a
persistent

®


transient
®

DB
delete
happens on
Session
flush
®

Java object normally lives until garbaged
© by Nicus for SDA
Under the hood
Under the hood
Runtime bytecode generation
(CGLIB project “code generation library”)
Create proxies extending persistent classes:

Intercept property changes (ditry check)

Allow lazy loading
Uses special impl. of Collections

Intercept element changes
Client application holds
CGLIB-generated subclasses
© by Nicus for SDA
Query interfaces
Query interfaces

(Retrieving by OID)

HQL

Criteria
API


Query by Example (QBE)

Native
SQL
Different
behavior!
© by Nicus for SDA
Object-Relational mapping
Object-Relational mapping
example
example
<class

name
=
”AuctionItem”
table
=”AUCTION_ITEMS”
>
<id

name
=”id”
column
=”ITEM_ID”
>
<generator

class
=”native”
/>
</id>
<property

name
=”description”
column
=”DESCR”
/>
...
<many-to-one

name
=”successfulBid”
column
=”SUCCBID_ID”
/>
<set

name
=”bids”
cascade
=”all”
lazy
=”true”
>
<key

column
=”ITEM_ID”
/>
<one-to-many

class
=”Bid”
/>
</set>
</class>
© by Nicus for SDA
HQL (examples)
HQL (examples)
from
AuctionItem
select
item
from AuctionItem item
join
item.bids
as
bid
where
item.description like “Hibernate%”
and bid.amount > 100
from AuctionItem item
where
item.successfulBid.qty
>
:minQty
from AuctionItem item
left join fetch
item.bids
where item.description=”Hibernate”
© by Nicus for SDA
HQL (API)
HQL (API)
Query
q =
session.createQuery(

from Users u where u.username = :uname
”);
q.
setString
(“uname”, userName);
List results = q.
list
();
© by Nicus for SDA
Criteria API (example)
Criteria API (example)
List auctionItems =
session.createCriteria(AuctionItem.class)
.add( Expression.like(“decription”, desc) )
.createCriteria(“successFulBid”)
.add( Expression.gt(“qty”, minQty) )
.setFetchMode(“bids”, FetchMode.EAGER)
.list();
HQL equivalent:
from AuctionItem item
left fetch join item.bids
where item.description like :descr
and item.successfulBid.qty > :minQty

© by Nicus for SDA
Criteria: QBE
Criteria: QBE
AuctionItem
exampleItem
= new AuctionItem();
exampleItem.
setDescription
(“Hibernate”);
Criteria criteria =
session.createCriteria(AuctionItem.class);
criteria.add(
Example.create
(exampleItem) );
List results = criteria.list();

Use example instance properties to create query

Useful with basic user defined queries

(Not very powerful)
© by Nicus for SDA
Details
Details
Agenda

Identity and equality

Cache

Mapping entity associations

Association fetching strategies

Cascading

Joins

Components

Mapping inheritance

Polymorphism

n+1 selects problem

Long Transactions
© by Nicus for SDA
Entity Object Id
Entity Object Id

<id name=”...” column=”...”>

Generated by Hibernate, Application or DB

Surrogate keys
!
Natural (composite) keys

Null-able OID property
®

use Long
Hibernate detects transient Entities by ID
value
(default=null)
© by Nicus for SDA
Identity & Equality
Identity & Equality

Java object
Identity
®

==

Java object
Equivalence
®

.equals()

Persistent Object ID (OID)
®
id
property
.equals()

Database Identity
®
same DB row
Do NOT implement
equals()
as OID equality!
© by Nicus for SDA
Cache
Cache
1
st
level cache
(
Session
)

Automatic
(may not be disabled)

Session-
wide (single thread)

Entity
(Object) cache

Enforce isolation
2
nd
level cache

Optional

External cache provider (pluggable)

VM or Cluster-wide

May be enabled
per-class

Value
cache

Degrade isolation

(good for immutable entities)
© by Nicus for SDA
Session & cache
Session & cache

Session:

single thread
(
HttpRequest
)

Session-wide cache for persistent (attached)
Objects guarantees
single instance of
persistents

(
while in
Session
)

Object Identity
º
DB Identity

Consistency of changes

No circular reference problem
Session
: 1
st
level cache, automatic, not configurable
© by Nicus for SDA
Mapping Associations
Mapping Associations

many-to-one
: normal single instance reference
(FK reference)

one-to-many
: Collection association

one-to-one
: PK, single instance reference

Association are
inherently unidirectional

Consider
persisted association like normal Java
association
®
Hibernate DO NOT manage
association for you!

Bidirectional assoc. should have a main direction for
db update (
inverse
=”true”
) just for update
efficiency
© by Nicus for SDA
Association fetching strategies
Association fetching strategies

Lazy
fetching
Associated object(s) fetched on demand
(using other SQL
selects
)
It works only for object attached to a (live)
Session

Eager
fetching
Associated object(s) fetched with parent using SQL
outer join
(only one association may be fetched eagerly)

Batch fetching
“look ahead” fetching of associated object(s), in blocks
© by Nicus for SDA
Single association fetching
Single association fetching
Single associations (
many-to-one
,
one-to-one
):

Lazy fetching possible only if
referred
object
enable
proxying
(
<class... lazy=“true”
or
proxy=“...”
)

Configured by association
outer-join
=“...”
(usually may leave default
outer-join=“auto”
)
© by Nicus for SDA
Collection fetching
Collection fetching

Eager
-fetching (
outer-join= “true”
)

outer-join” setting is
ignored by HQL
!
®

fetch join
syntax

Lazy
-fetching (
lazy=“true”
)
<set name=”bids”
lazy=“true”
>
<key column=”ITEM_ID”/>
<one-to-many class=“Bid”/>
</set>
Suggestion:

always define Collection as
lazy
in mapping

be sure that
Session
is open
when accessing
associated objects
© by Nicus for SDA
Lazy-fetching pitfall
Lazy-fetching pitfall
Lazy-fetched association:
automatically initialized when any
method/property of referenced object (other
than ID) are accessed
Lazy-fetched association
works only in
Session
!
You may force manual initialization:
Hibernate.initialize(item.getBids());
© by Nicus for SDA
Cascading persistence
Cascading persistence
Parent
®
(cascade)
®
Child
DO
Influence making Child persistent/transient when
associated/removed to/from Parent
DO NOT
influence db sync of changes on persistent Child
(while in Session): this is automatic!
behavior is specified
per-association
© by Nicus for SDA
Cascading persistence
Cascading persistence
(strategies)
(strategies)

cascade=“
none

(default)

cascade=“
save-update

:
save newly instantiated
(transient) and newly associated Child when Parent is
save(),

update()
or
saveOrUpdate()

cascade=“
delete

:
delete a persistent Child (make
transient) when Parent is
delete()

cascade= “
all

:
as
save-update
+
delete

cascade=“
all-delete-orphan

:
as
all
+ delete
persistent Child removed from association (dereference)

cascade=“
delete-orphan

:
only delete orphan
© by Nicus for SDA
Joins
Joins
!= SQL
!= SQL

Ordinary join (with alias)
(
...
from Parent as p left outer join p.child as c
...
)
join condition is implicit (mapped association)
returns Object[]

Fetch join
(
...
from Parent left join fetch Child
...
)
force Eager-fetching of (mapped) association
returned List is not distinct!
®

Encapsulate in Set

Theta-style join
(
...
from Parent p, Child c where p.x=c.y
...
)
useful if association is not mapped

Implicit association join
(...
where p.child.property=”x”
...)
N/A with Criteria API
© by Nicus for SDA
Fine-grained persistence
Fine-grained persistence
Components
Components

More classes than tables”

Entities (lifecycle, relationships)

Values (no identity, “embedded” state)
<class name=”User” table=”USERS”>
...
<component name=”address”>
<property name=”street” column=”STREET”/>
<property name=”city” column=”CITY”/>
...
</component>
</class>
id: Long
name: String
pwd: String
...
User
street: String
city: String
...
Address
address
© by Nicus for SDA
Mapping inheritance
Mapping inheritance

Table per concrete class
discard polymorphism and inheritance from relational
model
(almost) disallow polymorphic associaion/queries

Table per class hierarchy
use a type-discriminator column
performance benefits
denormalize relational model
subclass fields must be nullable

Table per subclass
represent inheritance as a FK relationship
normalized relational model
require a table even for Interfaces/Abstract classes
© by Nicus for SDA
Polymorphism
Polymorphism
Polymorphic associations
(single-point and collection)

Nothing to do :-)
Polymorphic queries

Nothing to do :-)
Pitfalls:

Hard with
table-per-concrete-class
mapping

If superclass is mapped
lazy

cannot typecast to subclasses or use
instanceof
(runtime-generated proxy extends superclass)
© by Nicus for SDA
N+1 selects problem
N+1 selects problem
from AuctionItem item where name=”Hibernate”
List maxQuantities = new Vector();
while ( items.hasNext() ) {
Item item = (AuctionItem) items.next();
int maxQty = 0;
for (Iterator b = items.getBids().iterator(); b.hasNext();) {
Bid bid = (Bid) b.next();
if ( bid.getQty() > maxQty ) maxQty = bid.getQty();
}
maxQuantities.add(new Integer(maxQty));
}
Persistence layer generates:

One
select to retrieve Parents (
AuctionItem
s)

N
select, to retrieve Childs (
Bid
s), one select for
each Parent
© by Nicus for SDA
N+1 selects problem (2)
N+1 selects problem (2)
a)
Map collection association
lazy
by default.
DO NOT map every collection “outer-join” (eagerly-
fetched), ignored by HQL, anyway...
b)
Fetch-eagerly locally, when n+1 selects
may be a problem
HQL
®

fetch join
Criteria
®

setFetchMode(...,FetchMode.EAGER)
© by Nicus for SDA
Long (business) Transactions
Long (business) Transactions
Strategies
a)
Save
Session
in
HttpSession
(not suggested!)
Session
+
Transaction
live more than one Request.
Use explicit pessimistic locking (deadlock!).
Remember to
disconnect()
and
reconnect()
the
Session
in
each
HttpRequest
!
b)
Use
Optimistic Locking
Session
+
Transaction
live for one
HttpRequest
.
Hibernate auto-implement optimistic locking by versioning.
If the (reattached) object has been changed in other
Transactions,
StaleObjectStateException
is thrown
®
must
be handled by UI logic
Multiple-HttpRequest transactions
© by Nicus for SDA
Reference docs
Reference docs


Hibernate in Action

(C.Bauer, G.King - Manning Publ)


Hibenate Reference Manual”
(
www.hibernate.org
)


Object-Relational Mapping”
(Scott Amblers -
www.ambysoft.com/mappingObjects.pdf
)


Mapping Associations”
(from “Road to Hibernate”)
(Michael Glögls -
www.gloegl.de/15.html
)


Design Patterns”
(from “Hibernate Community
Documentation”)
(www.hibernate.org/40.html)
© by Nicus for SDA
Q&A
Q&A
The End