You are on page 1of 35

Working with

objects
Content
1. Object states
2. Making objects persistent
3. Loading an object
4. Querying
5. Modifying persistent , detached objects
6. Automatic state detection
7. Deleting persistent object
8. Flushing the Session
9. Transitive persistence
States of an object and transitions
Object States
 Transient Object
 It has just been instantiated using the new operator, and it
is not associated with a persistence context.
 It has no persistent representation in the database and has
no a persistent identity.
 Persistent Object
 Just have been saved or loaded.
 An instance with a persistent identity that is currently
associated with a persistence context.
 Persistence provider (Hibernate) will detect any changes
made to an object in persistent state and synchronize the
state with the database when the unit of work completes
Object States
 Detached Object
 an object that has been persistent, but its persistence
context has been closed.
 The reference to the object is still valid, and might even be
modified
 A detached instance can be reattached to a new persistence
context at a later point in time, making it (and all the
modifications) persistent again by calling
 Removed Object
 an instance with a persistent identity, associated with a
persistence context, is scheduled for removal from the
database.
The persistence context
 a cache of managed entity instances
 In a Hibernate application, one Session has one internal persistence
context. In a Java Persistence application, an EntityManager has a
persistence context.
 Within the persistence context, the entity instances and
their lifecycle is managed by a session (entity manager)
 The session (entity manager) tracks all entity instances within a
persistence context for changes and updates made, and flushes these
changes to the database.
 Once a persistence context is closed, all managed entity instances are
no longer managed (detached), and any state changes to this instance
will not be synchronized with the database.
Making objects persistent
 We can make a transient instance persistent by
associating it with a session.
HourlyEmployee fritz =
new HourlyEmployee();
// fritz is in transient state
fritz.setName("Fritz");
fritz.setAddress('Paris');
Long generatedId =
(Long)sess.save(fritz);
// fritz is in persistent state
 You may assign the identifier
sess.save(fritz, new Long(1234));
JPA: Persisting an Entity Instance
 A new entity instance becomes both managed and
persistent by invoking the persist() method on it
Customer fritz =
new Customer("Hoang", "Nguyen");
em.persist(fritz);
 If the Customer entity type has a generated identifier, the value is
associated to the instance when persist() is called.
 If the identifier is not automatically generated, the application-
assigned (usually natural) key value has to be set on the instance
before persist() is called.
Loading an object
 If you already know its identifier, using load()
HourlyEmployee fritz =
(HourlyEmployee)
sess.load(HourlyEmployee.class,
empId);
 Can load state into a given instance:
Employee employee = new Employee();
// load pk's state into employee
sess.load(employee, empId);
 load() will throw an unrecoverable exception if
there is no matching database row
Loading an object
 If you are not certain that a matching row exists, you
should use the get() method, which returns null if
there is no matching row
Customer customer = (Customer)
sess.get(Customer.class, id);
if (customer==null) { ... }
 Can load an object using an SQL SELECT ... FOR
UPDATE, using a LockMode.
Customer customer = (Customer)
sess.get(Customer.class,
id,
LockMode.UPGRADE);
Loading an object
 It is possible to re-load an object and all its
collections at any time, using the refresh()
method.
sess.save(customer);
// force the SQL INSERT
sess.flush();
// re-read the state after the trigger executes

sess.refresh(customer);
 This is useful when database triggers are used to
initialize some of the properties of the object.
JPA: Loading an object
 Load an entity instance by its identifier value with
the entity manager's find() method:
Customer c =
em.find(Customer.class, cusId);
 Can reload an entity instance and it's collections
at any time using the em.refresh() operation
Querying
 If you don't know the identifiers of the objects you
are looking for, you need a query.
 Hibernate supports an easy-to-use but powerful
object oriented query language (OOQL).
 For programmatic query creation, Hibernate
supports a sophisticated Criteria and Example
query feature (QBC and QBE).
 You may also express your query in the native
SQL of your database, with optional support from
Hibernate for result set conversion into objects.
Executing Query
 Queries are represented with an instance of
org.hibernate.Query.
 You obtain a Query using the current Session:
Query query = session
.createQuery("FROM Employee AS emp WHERE " +
"emp.birthdate < ?");
query.setDate(0, date);
 A query is executed by invoking list()
List empployees = query.list();
 might execute the query using the iterate()
Iterator iter = sess.createQuery(
"FROM Employee AS emp ORDER BY emp.name")
.iterate();
JPA: Executing Query
 Queries are represented with an instance of
javax.persistence.Query.
 obtain a Query using the current entity manager:
Query query = em.createQuery(
"SELECT emp FROM Employee AS emp
WHERE emp.birthdate < ?1");
query.setParametter(1, date,
TemporalType.DATE);
 A query is executed by invoking getResultList()
List empplyees =
query.getResultList();
Queries that return tuples
 Queries sometimes return tuples of objects, in which case each tuple is
returned as an array:
Query query = session.createQuery("SELECT emp,
dep FROM Employee AS emp JOIN
emp.depatment AS dep");
Iterator iter = query.list().iterator();
while (iter.hasNext()){
Object[] objs = (Object[])iter.next();
Employee emp = (Employee) objs[0];
Depatment dep = (Depatment) objs[1];
}
Scalar results
 Queries may specify a property of a class and SQL aggregate
functions in the select clause. They are considered "scalar"
results
Query query = session.createQuery(
"SELECT emp.name, emp.email " +
"FROM Employee AS emp");
Iterator iter = query.list().iterator();
while(iter.hasNext()){
Object[] row = (Object[])iter1.next();
String name = (String) row[0];
String email = (String) row[1];
}
Bind parameters
 Methods on Query are provided for binding values
to named parameters or JDBC-style ? possitonal
parameters.
 Hibernate numbers parameters from zero.
 Named parameters are identifiers of the form
:name in the query string.
 The advantages of named parameters are:
 named parameters are insensitive to the order they occur in
the query string
 they may occur multiple times in the same query
 they are self-documenting
Bind parameters - Examples
Named parameter (preferred)
List emps = sess.createQuery(
"from HourlyEmployee emp where emp.name = :pname")
.setString("pname", "Fritz").list();

Positional parameter
Iterator emps = sess.createQuery(
"from DomesticCat cat where cat.name=? and cat.age=?")
.setString(0, "Izi")
.setInteger(1, 12).iterate();

Named parameter list


List names = new ArrayList();
names.add("Izi");
names.add("Fritz");
Query q = sess.createQuery("from DomesticCat cat " +
"where cat.name in (:namesList)");
q.setParameterList("namesList", names);
List cats = q.list();
JPA - Bind parameters
 Methods on Query are provided both named and
positional query parameters
 JPA numbers parameters from one.
 Named parameters are identifiers of the form
:paraname in the query string.
 The advantages of named parameters are:
 named parameters are insensitive to the order they occur in
the query string
 they may occur multiple times in the same query
 they are self-documenting
JPA - Bind parameters - Examples
Named parameter (preferred)
Query q = em.createQuery(
"SELECT e FROM HourlyEmployee e WHERE e.name = :pname");

q.setParameter("pname", "Paul");
List emps getResultList();

Positional parameter
Query q = em.createQuery("SELECT e FROM Employee e WHERE
e.name LIKE ?1 and e.wage > ?2");
q.setParameter(1, "Smith");
q.setParameter(2, 1200);
List emps = getResultList();

Named parameter list


List names = new ArrayList();
names.add("Anna");
names.add("Smith");
Query q = em.createQuery("SELECT e FROM Employee e WHERE

e.name IN (:namesList)");
Pagination
 Can specify bounds upon your result set
 The maximum number of rows, and / or
 The first row you want to retrieve

 Example:
Query q =
sess.createQuery("from
Employee");
q.setFirstResult(20);
q.setMaxResults(10);
List cats = q.list();
Scrollable iteration
 If your JDBC driver supports scrollable
ResultSets, the Query interface may be used to
obtain a ScrollableResults object, which allows
flexible navigation of the query results.
 Example:
Query q = sess.createQuery(
"select emp from Employee emp "
+
"order by emp.name");
ScrollableResults cats =
q.scroll();
Externalizing named queries
 You may also define named queries in the mapping document
<query name ="team.by.name.and.city">
<![CDATA[
from Team as team where
team.name = ? and team.city = ?
]]></query>
 Parameter binding and executing is done programatically:
Query q = sess.getNamedQuery(
"team.by.name.and.city");
q.setString(0, name);
q.setString(1, city);
List cats = q.list();
JPA - Externalizing named queries
 Named queries can be defined in EJB QL or in SQL.
Query names are scoped to the persistence unit.
 Example
@NamedQuery(
name="findAllCustomersWithName",
query="SELECT c FROM Customer c WHERE c.name
LIKE :custName")
 Use of a named query:
customers =
em.createNamedQuery("findAllCustomersWithName")
.setParameter("custName", "Smith")
.getResultList();
Filtering collections.
 A collection filter is a special type of query that may be
applied to a persistent collection or array. The query string
may refer to this, meaning the current collection element .
 Example:
session.update(team);
Query query3 =
session.createFilter(team.getPlayers(),
"where this.firstname = ?");
Collection players = (Collection)
query3.setParameter(0, "nguyen").list();
Iterator iter = players.iterator();
while (iter.hasNext()){
Player p = (Player) iter.next();
System.out.println(p);
}
Criteria queries
 HQL is extremely powerful but some developers prefer
to build queries dynamically, using an object-oriented
API, rather than building query strings.
 Hibernate provides an intuitive Criteria query API for
these cases
 Example:
Criteria crit =
session.createCriteria(Team.class);
crit.add(Expression.eq("name","HAGL"))
;
Queries in native SQL
 You may express a query in native SQL, using createSQLQuery()
 If you chose to use the Hibernate API, you must enclose SQL aliases in
braces:
SQLQuery query = session
.createSQLQuery("select * from team");
query.addEntity(Team.class);
 or
SQLQuery query = session.createSQLQuery(
"select {team.*} from team {team}");
query.addEntity("team", Team.class);
Modifying persistent object
 Transactional persistent instances may be manipulated
by the application and any changes to persistent state
will be persisted when the Session is flushed
(automatically).
 So the most straightforward way to update the state of
an object is to load() it, and then manipulate it
directly, while the Session is open:
 Example:
DomesticCat cat = (DomesticCat)
sess.load( Cat.class, new Long(69));
cat.setName("PK");
sess.flush();
Modifying detached object
 To reattach of detached instances using the
Session.update() or Session.merge()
methods:
 Example:
// in the first session
SalaryEmployee emp = (SalaryEmployee)
firstSession.load(SalaryEmployee.class, empId);
Department dep = new Department();
firstSession.save(dept);
// in a higher layer of the application
emp.setDepartment(dep);

// later, in a new session


secondSession.update(emp); // update employee
Automatic state detection
 Using saveOrUpdate() method to either save a
transient instance by generating a new identifier
or updates/ reattaches the detached instance
associated with its current identifier.
 Example:
// in the first session
SalaryEmployee emp = (SalaryEmployee)
firstSession.load(SalaryEmployee.class, empId);
Department dep = new Department();
// in a higher layer of the application
emp.setDepartment(dep);
// later, in a new session
secondSession.saveOrUpdate(emp); // update employee
secondSession.saveOrUpdate(dep); // update department
Deleting persistent object
 Using method Session.delete() will remove
an object's state from the database.
 your application might still hold a reference to a deleted
object. It's best to think of delete() as making a persistent
instance transient.
 You may delete objects in any order you like,
without risk of foreign key constraint violations. It
is still possible to violate a NOT NULL constraint
on a foreign key column by deleting objects in the
wrong order, e.g. if you delete the parent, but
forget to delete the children.
Flushing the Session
 Except when you explicity flush(), there are
absolutely no guarantees about when the Session
executes the JDBC calls.
 The FlushMode class defines three different
modes:
 Only flush at commit time (and only when the Hibernate
Transaction API is used).
 Flush automatically using the explained routine.
 Never flush unless flush() is called explicitly.
Flushing the Session
//allow queries to return stale state
Cat izi = (Cat) sess.load(Cat.class, id);
izi.setName(iznizi);
// might return stale data
sess.find("from Cat as cat left outer join
cat.kittens kitten");
// change to izi is not flushed! ...
tx.commit(); // flush occurs
sess.close();
Transitive persistence
 For each basic operation of the Hibernate session
including:
 persist(), merge(), saveOrUpdate(), delete(),
lock(), refresh(), evict(), replicate()
 create, merge, save-update, delete, lock,
refresh, evict, replicate.
 <one-to-one name="person" cascade="persist"/>
 <one-to-one name="person" cascade="persist,
delete, lock"/>.
 <one-to-one name="person" cascade="all"/>
 <one-to-one name="person" cascade="none"/>

You might also like