0% found this document useful (0 votes)
10 views

Module 02 - Hibernate Persistence-upd

ea lect2

Uploaded by

surafelbehailu90
Copyright
© © All Rights Reserved
Available Formats
Download as PDF, TXT or read online on Scribd
0% found this document useful (0 votes)
10 views

Module 02 - Hibernate Persistence-upd

ea lect2

Uploaded by

surafelbehailu90
Copyright
© © All Rights Reserved
Available Formats
Download as PDF, TXT or read online on Scribd
You are on page 1/ 45

Module 02: Persistence API

CS544: Enterprise Architecture

© 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:

ENTITY OBJECT LIFECYCLE

© 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

employee id firstname lastname


205 Frank Brown
id=205
firstname=“Frank”
lastname=“Brown”

© 2014 Time2Master 7
Detached entity
 A detached entity has a database identity,
but is not managed by the current
persistence context

The state of a detached


persistence context
entity does not need to
be the same as the
state in the database

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:

STORING ENTITY OBJECTS

© 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);

Saves the entity and Persists the entity but


returns its generated id does not return anything

 Save() will always insert right away (eager)


 Persist() will insert when it needs to (lazy)

© 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

Person p1 = new Person("Frank Brown"); Person p1 = new Person("Frank Brown");


long id1 = (Long)session.save(p1); session.persist(p1);

Saves the entity and Will persists the entity


returns its generated id but may not do so now,
can therefore not
guarantee a return id

© 2014 Time2Master 13
Persistence API:

RETRIEVING ENTITY OBJECTS

© 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);

Person p1 = (Person) session.load(Person.class, 1L);

 Get() retrieves the object’s values right away


 Load() provides a proxy and does not retrieve
the object’s values until they are first needed
© 2014 Time2Master 15
get()
1. Product product = (Product)session.get(Product.class, new Long(productid));

Filled Product object


product Goes to the database
db
persistence context If the product with
this id does not exist,
get() returns null

2. product.getPrice()

Filled Product object


product
No database access
db
persistence context

© 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()

Filled Product object


product Goes to the database
db
If the product with
persistence context
this id does not exist,
Hibernate throws an
exception

© 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

The load() method creates an Employee proxy


object in the persistence context, set its id, but
does not hit the database.

Employee employee = (Employee) session.load(Employee.class, employeeid );


session.delete(employee);

 1 database hit
 1 DELETE statement for the delete() method
© 2014 Time2Master 18
Persistence API:

UPDATING ENTITY OBJECTS

© 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();
}
}

 Hibernate notices that an object is ‘dirty’ and


uses a SQL UPDATE to push it to the database
© 2014 Time2Master 20
About: update()
 You can also explicitly call the update() method
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("Explicitly Updated");
session.update(p3); Object is changed
Explicit update()
tx.commit();
} catch (HibernateException e) {
tx.rollback(); Change is pushed to the database
e.printStackTrace(); when the transaction commits
} finally {
if (session != null) {
session.close();
}
}

 Like the implicit update, changes are not pushed to


the database until the transaction is committed

© 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

 The real power of the explicit update() is in


re-attaching detached objects that have been
updated outside of the persistence context
 Once attached their changes will also be
pushed to the database on commit()

© 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();

p1.setName("Detached Update"); Detached update

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

Detached object Solution: use merge()


© 2014 Time2Master 24
Exception Example
session = sessionFactory.openSession();
Person p1 = new Person("Frank Brown");
long id = (Long)session.save(p1);
Session.close() System.out.println("Frank Brown Id: " +id); Output shows id=1
makes p1 detached session.close();

try { New session, new


session = sessionFactory.openSession();
tx = session.beginTransaction();
persistence context

Person p2 = (Person)session.get(Person.class, 1L); Loads person with


session.update(p1); id=1 (Frank Brown)
Tries to re-attach
p1, also id=1 into the persistence
tx.commit();
(Also Frank Brown) context
} catch (HibernateException e) {
tx.rollback();
e.printStackTrace();
} finally {
if (session != null) {
session.close();
}
Output:
Hibernate: /* insert entity.Person */ insert into Person (id, name) values (null, ?)
Hibernate: call identity()
Frank Brown Id: 1
Hibernate: /* load entity.Person */ select person0_.id as id0_0_, person0_.name as name0_0_
from Person person0_ where person0_.id=?
org.hibernate.NonUniqueObjectException: a different object with the same identifier value was
already associated with the session: [entity.Person#1]
Exception
© 2014 Time2Master 25
Merge – Avoids the Exception
persistence context

Copy state id firstname lastname


id=105 id=105
105 Frank Brown
firstname=“Frank” firstname=“Frank”
lastname=“Update” lastname=“Brown”

Merge avoids the exception


Then returns by copying the object state
the existing , into the existing object
managed object

The database gets


updated on commit
persistence context

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)

 If you continue working with the original


object you can run into unexpected problems,
implicit updates to it are not persisted

© 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

Does the entity have a


generated or an assigned Id?
Generated Assigned

Id is null Does not Does its Id already exist


Is the id field null?
Save (INSERT) in the database?
(not generated yet)
(SELECT)

Not null Update (UPDATE) Exists

© 2014 Time2Master 29
Persistence API:

REMOVING ENTITY OBJECTS

© 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

Person p1 = (Person) session.load(Person.class, 1L);


Delete entity session.delete(p1);

tx.commit(); SQL DELETE is not


} catch (HibernateException e) { executed untill the
tx.rollback(); transaction commits
e.printStackTrace();
}

© 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"); }

tx.commit(); Hibernate will access the


System.out.println("5"); database during the commit() to
update the state of the changed
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=?
5

© 2014 Time2Master 35
When does Hibernate access the DB?
session = sessionFactory.openSession();
tx = session.beginTransaction();

Employee fmemployee = new Employee("Frank", "Miller");


System.out.println("1");
session.persist(fmemployee);
System.out.println("2");
fmemployee.setFirstname("John");
System.out.println("3");
fmemployee.setLastname("Doe");
System.out.println("4");
Employee jdemployee= (Employee)session.get(Employee.class, fmemployee.getId());
System.out.println("5");
No database access,
tx.commit(); object is already in the
System.out.println("6"); persistence context

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 {

Employee fmemployee = new Employee("Frank", "Miller"); @Id


System.out.println("1"); @GeneratedValue
session.persist(fmemployee); private int id;
System.out.println("2"); private String firstname;
fmemployee.setFirstname("John"); private String lastname;
System.out.println("3"); …
fmemployee.setLastname("Doe"); }
System.out.println("4");
Query query= session.createQuery("from Employee");
Collection<Employee> employeelist= query.list(); Query on Employee, and we have a dirty
System.out.println("5"); Employee in the persistence context. First
tx.commit();
update the Employee in the database, and
System.out.println("6"); then execute the query

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);

p1.setName("Frank Updated"); Creates changes to


p2.setName("John Updated"); the objects in the DB Result:
session.delete(p3); persistence cache mysql> select * from person;
+----+---------------+
System.out.println("About to flush()"); | id | name |
session.flush(); flush() everything +----+---------------+
System.out.println("Changes flushed"); | 1 | Frank Updated |
| 2 | John Updated |
tx.commit(); +----+---------------+
session.close();
No changes left to commit()

Flush() commits all changes held in cache


Hibernate Output:
About to flush()
Hibernate: /* insert entity.APerson */ insert into APerson (name, id) values (?, ?)
Hibernate: /* insert entity.APerson */ insert into APerson (name, id) values (?, ?)
Hibernate: /* insert entity.APerson */ insert into APerson (name, id) values (?, ?)
Hibernate: /* update entity.APerson */ update APerson set name=? where id=?
Hibernate: /* update entity.APerson */ update APerson set name=? where id=?
Hibernate: /* delete entity.APerson */ delete from APerson where id=?
Changes flushed
© 2014 Time2Master 39
When are changes Flushed?
 There are actually 3 different scenarios under
which Hibernate will commit all changes
1. When an explicit session.flush() call is made
2. When a transaction is committed
3. Inside a transaction, before a query to the
database is executed
persistence context

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

Although a transaction is not


required, it is recommended
session = sessionFactory.openSession(); to alway use a transaction
tx = session.beginTransaction();

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());

tx.commit(); Specifically refresh() to check


} catch (Exception e) { the database for updates
...
Hibernate Output:
Hibernate: /* load entity.Person */ select person0_.id as id0_0_,
person0_.name as name0_0_ from Person person0_ where person0_.id=?
Frank Brown
refresh() checks Slept for 5 minutes
the database and No db check, just cache
Frank Brown
finds that it has Hibernate: /* load entity.Person */ select person0_.id as id0_0_,
been updated! person0_.name as name0_0_ from Person person0_ where person0_.id=?
Frank Upd.

© 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?

 What are the similarities and the differences


between saveOrUpdate() and merge()?

© 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

You might also like