Module 02 - Hibernate Persistence-upd
Module 02 - Hibernate Persistence-upd
© 2014 Time2Master 1
Object Persistence
So far we’ve only discussed the basics of
mapping classes to tables
In this module we will discuss Hibernates
object management
We will look at the different states of the
entity lifecycle, and the methods that are used
to move objects between them
We will also provide insight into the
differences between some of Hibernates
seemingly duplicate methods
© 2014 Time2Master 2
Persistence API:
© 2014 Time2Master 3
Lifecycle of an entity
Transient
new
save()
persist() Removed
get() saveOrUpdate()
load() merge() delete()
Query.list()
Persistent / Managed
Query.iterate() refresh()
Query.scroll()
Query.uniqueResult() evict() update()
Query.getResultList() session.close() saveOrUpdate()
Query.getSingleResult() session.clear() merge()
Detached
© 2014 Time2Master 4
Persistence context
Manages the entities
Guarantees that managed enities will be saved
in the database
Tracks changes until they are pushed to the
database
Works like a cache
persistence context
entity
application entity DB
entity entity
entity
© 2014 Time2Master 5
Transient entity
A transient entity has no database identity
persistence context
id firstname lastname
employee
id=null
firstname=“Frank”
lastname=“Brown”
© 2014 Time2Master 6
Managed entity
A managed entity is managed by the
persistence context and has a database
identity
persistence context
© 2014 Time2Master 7
Detached entity
A detached entity has a database identity,
but is not managed by the current
persistence context
id firstname lastname
205 Frank Brown
employee
id=205
firstname=“Frank”
lastname=“Brown”
© 2014 Time2Master 8
Removed entity
With a removed entity is the corresponding
data removed from the database.
persistence context
id firstname lastname
employee
id=205
firstname=“Frank”
lastname=“Brown”
© 2014 Time2Master 9
Session - Persistence Context
Type Methods Description
CREATE session.persist() Uses SQL INSERT statements to
session.save() create rows in the database
RETRIEVE session.load() Uses SQL SELECT statments to
session.get() retrieve rows from the database
UPDATE *implicit update* Uses SQL UPDATE statements to
session.update() update rows in the database
CREATE / UPDATE session.saveOrUpdate() Uses either INSERT or UPDATE
session.merge() depending on the state of the object
DELETE session.delete() Uses SQL DELETE statements to
delete rows from the database
Cache related session.refresh() Explicitly gets changes from the
functions session.flush() database, explicitly pushes changes
to the database
© 2014 Time2Master 10
Persistence API:
© 2014 Time2Master 11
About: save() and persist()
Save() and persist() are very similar
Both will add the given entity to the persistence
context, and INSERT it into the database
Person p1 = new Person("Frank Brown"); Person p1 = new Person("Frank Brown");
long id1 = (Long)session.save(p1); session.persist(p1);
© 2014 Time2Master 12
Return value: save() / persist()
Because save() executes right away it can
guarantee to return the generated id
Persist() on the other hand may wait until the
end of the transaction to execute its INSERT
Persist() therefore returns void
© 2014 Time2Master 13
Persistence API:
© 2014 Time2Master 14
About: get() and load()
Get() and load() are very similar
Both retrieve an object by its primary key
SELECT * FROM … WHERE [primairy key] = …
If an entity is already cached the database is not hit
Person p1 = (Person) session.get(Person.class, 1L);
2. product.getPrice()
© 2014 Time2Master 16
load()
1. Product product = (Product)session.load(Product.class, new Long(productid));
proxy
product No database access
db
persistence context
2. product.getPrice()
© 2014 Time2Master 17
When to use load() instead of get()
Employee employee = (Employee) session.get(Employee.class, employeeid );
session.delete(employee);
2 database hits
1 SELECT statement for the get() method
1 DELETE statment for the delete() method
1 database hit
1 DELETE statement for the delete() method
© 2014 Time2Master 18
Persistence API:
© 2014 Time2Master 19
Implicit Update
When a managed entity is changed inside a
transaction, the changes are pushed to the
database when the transaction commits
Get () puts the object into
try { the persistence context
session = sessionFactory.openSession();
(becomes managed)
tx = session.beginTransaction();
Person p3 = (Person) session.get(Person.class, 1L);
p3.setName("Implicitly Updated");
tx.commit(); Object is changed
} catch (HibernateException e) {
tx.rollback(); Change is pushed to the database
e.printStackTrace(); when the transaction commits
} finally {
if (session != null) {
session.close();
}
}
© 2014 Time2Master 21
Implicit vs. Explicit update
In the last example the explicit update was
completely redundant – not needed
Why even have an explicit update() method?
session.update(detached_object); Update() can be used to re-attach
© 2014 Time2Master 22
Re-Attach Example
session = sessionFactory.openSession();
Person p1 = new Person("Frank Brown");
Session.close() session.save(p1);
makes p1 detached session.close();
try {
session = sessionFactory.openSession();
tx = session.beginTransaction();
Update re-attaches session.update(p1);
tx.commit();
Commit pushes updates of
} catch (HibernateException e) {
tx.rollback(); attached object to the db
e.printStackTrace();
} finally {
if (session != null) {
session.close();
}
}
session = sessionFactory.openSession();
Load object to check if Person p2 =(Person)session.get(Person.class, 1L); Person was updated
System.out.println("Name: " + p2.getName());
update was successful successfully
session.close();
Name: Detached Update
© 2014 Time2Master 23
The Problem with Re-Attaching
Update() will throw a
NonUniqueObjectException
when re-attaching an object with the same id as
an already managed object
When update() receives a persistence context
detached object for an
entity it is already managing employee
Hibernate will trow a
NonUniqueObjectException! id=105
firstname=“Frank”
id firstname lastname
lastname=“Brown” 205 Frank Brown
employee
Id=105
firstname=“Frank” Existing, already
lastname=“Update” managed object
id firstname lastname
id=105 id=105
105 Frank Brown
firstname=“Frank” firstname=“Frank”
lastname=“Update” lastname=“Update”
© 2014 Time2Master 26
Merge - Misunderstood
Merge does not behave like save(), update(),
and saveOrUpdate()
The object you pass in to merge never becomes
part of the persistence context (is not managed)
Instead merge returns an different object
representing the same entity (which is managed)
© 2014 Time2Master 27
Correct use of Merge
Correct Use of merge() – Always use the return value
Person p = new Person("Frank Brown");
try {
session = sessionFactory.openSession();
P is set to tx = session.beginTransaction();
the return
of merge() p = (Person)session.merge(p); Incorrect Use of merge()
p.setName("Upd. Frank Brown");
Person p = new Person("Frank Brown");
tx.commit(); Update will be
commited
} catch (HibernateException e) { try {
tx.rollback(); session = sessionFactory.openSession();
e.printStackTrace(); tx = session.beginTransaction();
} finally {
if (session != null) { Return is session.merge(p);
session.close(); p.setName("Upd. Frank Brown"); Update will
lost, P is
} never get
still the tx.commit();
} commited
detached } catch (HibernateException e) {
object tx.rollback();
e.printStackTrace();
} finally {
if (session != null) {
session.close();
}
}
© 2014 Time2Master 28
saveOrUpdate()
Hibernate checks if it needs to INSERT or
UPDATE
If needed using a SELECT to find if it’s already in the db
© 2014 Time2Master 29
Persistence API:
© 2014 Time2Master 30
About: delete()
Can be used to remove an entity from the db
Only managed entities can be removed
Will only work inside a transaction
On transaction.commit() a SQL DELETE is used
to delete the entity from the database
Load entity so that is
try {
session = sessionFactory.openSession(); managed in the
tx = session.beginTransaction(); persistence context
© 2014 Time2Master 31
Persistence API:
PERSISTENCE CACHE
© 2014 Time2Master 32
When does Hibernate access the DB?
@Entity
session = sessionFactory.openSession(); public class Employee {
tx = session.beginTransaction();
@GeneratedValue
@Id
Employee fmemployee = new Employee("Frank", "Miller"); @GeneratedValue
System.out.println("1"); private int id;
session.persist(fmemployee); Hibernate will access private String firstname;
System.out.println("2"); the database during the private String lastname;
persist() to retrieve the …
tx.commit();
unique key }
1
Hibernate: /* insert Employee */ insert into Employee (id, lastname) values (null, ?)
Hibernate: call identity()
2
© 2014 Time2Master 33
When does Hibernate access the DB?
@Entity
session = sessionFactory.openSession(); public class Employee {
tx = session.beginTransaction(); Application
@Id generates the id
Employee fmemployee = new Employee("Frank", "Miller"); private int id;
System.out.println("1"); private String firstname;
session.persist(fmemployee);
Hibernate will access private String lastname;
System.out.println("2"); …
the database during the
}
tx.commit(); commit()
System.out.println("3");
1
2
Hibernate: /* insert Employee */ insert into Employee (firstname, lastname, id) values
(?, ?, ?)
3
© 2014 Time2Master 34
When does Hibernate access the DB?
session = sessionFactory.openSession();
tx = session.beginTransaction(); @Entity
public class Employee {
Employee fmemployee = new Employee("Frank", "Miller");
System.out.println("1"); @Id
session.persist(fmemployee); @GeneratedValue
Hibernate will access
System.out.println("2"); private int id;
the database during the private String firstname;
fmemployee.setFirstname("John");
persist() to retrieve the private String lastname;
System.out.println("3");
fmemployee.setLastname("Doe"); unique key …
System.out.println("4"); }
1
Hibernate: /* insert Employee */ insert into Employee (id, firstname, lastname) values
(null, ?, ?)
Hibernate: call identity()
2
3
4
Hibernate: /* update Employee */ update Employee set firstname=?, lastname=? where id=?
5
© 2014 Time2Master 35
When does Hibernate access the DB?
session = sessionFactory.openSession();
tx = session.beginTransaction();
1
Hibernate: /* insert Employee */ insert into Employee (id, firstname, lastname) values
(null, ?, ?)
Hibernate: call identity()
2
3
4
5
Hibernate: /* update Employee */ update Employee set firstname=?, lastname=? where id=?
6
© 2014 Time2Master 36
When does Hibernate access the DB?
session = sessionFactory.openSession(); @Entity
tx = session.beginTransaction(); public class Employee {
1
Hibernate: /* insert Employee */ insert into Employee (id, firstname, lastname) values
(null, ?, ?)
Hibernate: call identity()
2
3
4
Hibernate: /* update Employee */ update Employee set firstname=?, lastname=? where id=?
Hibernate: /* from Employee */ select employee0_.id as id0_, employee0_.firstname as
firstname0_, employee0_.lastname as lastname0_ from Employee employee0_
5
6
© 2014 Time2Master 37
flush()
Flushes any changes held in the session
persistence context to the database
Any changes made by an implicit or explicit
update(), objects marked for deletion with
delete() or for persistence with persist()
All these changes can be committed to the
database immediately without having to wait
for the transaction to commit
session.flush();
© 2014 Time2Master 38
flush()
Person with
Session session = sessionFactory.openSession();
assigned identifier
@Entity
Transaction tx = session.beginTransaction(); public class APerson {
@Id
APerson p1 = new APerson("Frank Brown", 1); private long id;
APerson p2 = new APerson("John Doe", 2); private String name;
APerson p3 = new APerson("Mary Smith", 3);
session.persist(p1); Persist() does not insert entities ...
session.persist(p2);
with assigned ids right away
session.persist(p3);
entity
changed DB
entity
entity
changed
© 2014 Time2Master 40
refresh()
The entity object will immediately be
refreshed with the state currently held in the
database
Can be used to undo updates
session.refresh(p1);
Immediately refreshes with
tx.commit(); state from the database, re-
session.close();
attaches if detached
© 2014 Time2Master 41
Stale Cache – a Reason to Refresh
try {
session = sessionFactory.openSession();
tx = session.beginTransaction();
Retrieve a person entity and
Person p1 = (Person) session.get(Person.class, 1L); print its name (also puts it
System.out.println(p1.getName()); in the persistence cache)
Thread.sleep(1000 * 60 * 5);
System.out.println("Slept for 5 minutes"); Try to retrieve the same
entity again 5 minutes later
p1 = (Person) session.get(Person.class, 1L);
System.out.println(p1.getName());
Because of cache get() does
session.refresh(p1); not check the database!
System.out.println(p1.getName());
© 2014 Time2Master 42
Entity Manager API
Method Description
clear() Empties persistence context, managed entities become detached
close() Closes the entity manager, managed entities become detached
contains() Checks if the instance is managed by this entity manager
detach() Detaches the given entity
find() Retrieves and entity from the db by primary key
flush() Flushes all changes to the db
getReference() Get and instance by Id, state may be lazily fetched
merge() Merge the state of the given entity into the persistence context
persist() Make the instance managed and persistent
refresh() Update the state of the given entity from the db
remove() Delete the given entity from the db
http://docs.oracle.com/javaee/6/api/javax/persistence/EntityManager.html
© 2014 Time2Master 43
Active Learning
What are the four different states of the entity
lifecycle?
© 2014 Time2Master 44
Module Summary
In this module we discussed the object
persistence lifecycle and how to manage it
We presented the different methods
Hibernate provides on the Session object
Although several methods provide similar
functionality there are subtle differences
These differences are important for enterprise
applications and should be noted with care
We also demonstrated Hibernates caching
behavior and how it can be manipulated
© 2014 Time2Master 45