10 Hibernate JPA
10 Hibernate JPA
com
J
Java
P
Persistence
i t
API
Originals of Slides and Source Code for Examples:
http://courses.coreservlets.com/Course-Materials/hibernate.html
Customized Java EE Training: http://courses.coreservlets.com/
Servlets, JSP, Struts, JSF/MyFaces/Facelets, Ajax, GWT, Spring, Hibernate/JPA, Java 5 & 6.
Developed and taught by well-known author and developer. At public venues or onsite at your location.
2009 coreservlets.com
Courses developed
and taught
by EE
coreservlets.com
experts (edited by Marty)
Customized
Java
Training: http://courses.coreservlets.com/
Spring, Hibernate/JPA, EJB3, Ruby/Rails
Servlets, JSP, Struts, JSF/MyFaces/Facelets, Ajax, GWT, Spring, Hibernate/JPA, Java 5 & 6.
Contact
[email protected]
for details
Developed and taught by well-known
author
and developer. At public
venues or onsite at your location.
Topics
p
in This Section
Become acquainted
q
with the Java
Persistence API (JPA)
Compare and contrast Hibernate
and JPA
Learn how to setup and use
Hibernate as a JPA provider
2009 coreservlets.com
Si
Simplifies
lifi th
the d
development
l
t off J
Java EE
and Java SE applications using data
persistence
i t
Brings the Java community behind a
single,
i l standard
t d d persistence
i t
API
Draws upon the best ideas from
existing persistence technologies
Hibernate, TopLink, and JDO
E
Existing
i ti EJB CMP applications
li ti
continue to work unchanged
May
M become
b
partt off Java
J
SE
Likely that this issue will be considered by
th Java
the
J
SE expertt group in
i a future
f t
Java
J
SE release
EntityManagerFactory
y
EntityTransaction
Persistence Unit
persistence.xml
Hibernate
Entity Classes
Persistent Classes
E tit M
EntityManagerFactory
F t
S
SessionFactory
i F t
EntityManager
Session
Persistence
Configuration
E tit T
EntityTransaction
ti
T
Transaction
ti
Query
Query
Persistence Unit
Hibernate Config
Persistence Unit
Defines all entity classes that are
managed by JPA
p
Identified in the persistence.xml
configuration file
Entity
y classes and configuration
g
files are packaged together
The JAR or directory that contains the
persistence.xml
i
l is
i called
ll d the
h root off the
h
persistence unit
Needs to be inside a META-INF directory
Whether or not inside a jar
p
persistence.xml
<persistence xmlns="http://java.sun.com/xml/ns/persistence"
xmlns:xsi http://www.w3.org/2001/XMLSchema instance
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://java.sun.com/xml/ns/persistence
http://java.sun.com/xml/ns/persistence/persistence_1_0.xsd"
version="1.0">
<persistence-unit name="BankingApp">
<provider>
org.hibernate.ejb.HibernatePersistence
hib
t
jb Hib
t P
i t
</provider>
<mapping-file>orm.xml</mapping-file>
<cl ss>c
<class>courses.hibernate.vo.Account</class>
s s hib
t
Acc
t</cl ss>
<class>courses.hibernate.vo.AccountOwner</class>
<class>courses.hibernate.vo.AccountTransaction</class>
<class>courses hibernate vo EBill</class>
<class>courses.hibernate.vo.EBill</class>
<class>courses.hibernate.vo.EBiller</class>
...
p
persistence.xml
...
<properties>
properties
<!-- VENDOR SPECIFIC TAGS -->
<property name="hibernate.connection.driver_class"
value="oracle.jdbc.driver.OracleDriver"/>
<property name="hibernate.connection.url"
value="jdbc:oracle:thin:@localhost:1521:XE"/>
<property name="hibernate.connection.username"
value="lecture10"/>
<property name="hibernate.connection.password"
value="lecture10"/>
<property name="hibernate.dialect"
value="org.hibernate.dialect.Oracle10gDialect"/>
<property name="hibernate.show_sql"
value="true"/>
</properties>
/
ti
</persistence-unit>
</persistence>
persistence.xml: Pass-Through
p
g
Can satisfy the persistence.xml requirement
with
ith a pass th
through
h to
t an existing
i ti Hibernate
Hib
t
configuration file
<persistence-unit name="BankingApp">
<properties>
<property name="hibernate.ejb.cfgfile"
value="/hibernate.cfg.xml"/>
</properties>
</persistence-unit>
</persistence
Auto Entity
y Detection
JPA provides for auto detection
No need to list individual Entity classes in persistence.xml.
Looks for annotated classes and mapping files
Specification requires use of <class>
class tags in non
nonEE
EE
environment, but Hibernate supports the functionality in
both
Does NOT work with nonJPA
non JPA Hibernate
<persistence-unit name="BankingApp">
Enabled by default
...
<property
name="hibernate.archive.autodetection"
value="class hbm*"/>
value="class,
...
</persistence-unit>`
Entity
y Classes
Managed objects mapped in one of two ways
Described in the orm
orm.xml
xml mapping file
Marked with annotations in individual classes
Identified as managed with @Entity
Primary key identified through the @Id
orm.xml Mapping
pp g File
<entity-mappings
xmlns="http://java
xmlns=
http://java.sun.com/xml/ns/persistence/orm
sun com/xml/ns/persistence/orm"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation=
http://java.sun.com/xml/ns/persistence/orm_1_0.xsd
1 0.xsd"
"http://java.sun.com/xml/ns/persistence/orm
version="1.0">
<persistence-unit-metadata>
<!-!
id tifi
identifies
the
th orm.xml
l as the
th only
l source
for class definition, telling the engine
to ignore annotations in classes -->
< ml mapping metadata complete/>
<xml-mapping-metadata-complete/>
<persistence-unit-defaults>
<cascade-persist/>
</persistence-unit-defaults>
</persistence-unit-metadata>
...
orm.xml Mapping
pp g File
...
<package>courses.hibernate.vo</package>
<entity class=
class="Account"
Account access=
access="FIELD">
FIELD >
<table name="ACCOUNT" />
<attributes>
<id name="accountId">
<col mn name="ACCOUNT_ID"
<column
name "ACCOUNT ID" />
<generated-value strategy="AUTO" />
</id>
<basic name="balance" optional="false">
<column name="BALANCE" />
</basic>
<version name="version">
<column name="VERSION" />
Notice no type definitions!
Notice,
</version>
<attributes>
</entity>
</entity-mappings>
</entity
mappings>
Annotations: Property
p y Access
@Entity
public class Account {
private long accountId;
...
@Id
@GeneratedValue(strategy=GenerationType.AUTO)
@Column(name="ACCOUNT_ID")
public long getAccountId() {...}
public void setAccountId(long newId) {...}
...
}
Account Entity:
y Field Access
@Entity
public class Account {
@Id
@GeneratedValue(strategy=GenerationType.AUTO)
@C l
@Column(name="ACCOUNT_ID")
(
"ACCOUNT ID")
private long accountId;
...
public long getAccountId() {...}
public void setAccountId(long newId) {...}
...
}
EntityManagerFactory
y
g
y
Used to create EntityManager in
JavaSE environment
Similar to Hibernate SessionFactory
EntityManagerFactory emf =
Persistence
.createEntityManagerFactory("BankingApp");
EntityManager
y
g
Creates and removes persistent
p
entity instances
Finds entities by their primary key
Allows for data querying
Interacts
I t
t with
ith the
th persistence
i t
context
Similar to Hibernate Session
EntityManager
y
g
clear()
close()
contains()
createNamedQuery()
createNativeQuery()
getTransaction()
lock()
persist()
refresh()
remove()
find()
setFlushMode()
Application Managed
EntityManager
Created and destroyed explicitly by the
application
g the
Created through
EntityManagerFactory class
EntityManagerFactory
i
emf =
Persistence
.createEntityManagerFactory("BankingApp");
y
g
y(
g pp );
EntityManager em = emf.createEntityManager();
Container Managed
EntityManager
Used with Enterprise
p
Java Beans
Automatically propagated to all
application components within a
single Java Transaction API (JTA)
transaction
Need to identify data source in
persistence.xml
it
l file
fil
Annotate an Entity
y Manager
g
public class AccountSessionBean {
@PersistenceContext
EntityManager em;
public Account getAccount(int accountId){
Account account =
em.find(Account.class, accountId);
return account;
}
}
Inject
j
an EntityManagerFactory
y
g
y
Inject an EntityManagerFactory into
your EJB for more manual control
public class AccountSessionBean {
@PersitenceUnit(unitName="BankApp")
EntityManagerFactory emf;
public Account getAccount(int accountId){
EntityManager em =
emf.createEntityManager();
y
g ();
Account account =
em.find(Account.class, accountId);
return account;
}
}
Save an Entity
y in Java SE
public void saveAccount(Account account) {
EntityManager em =
JPAUtil.getEntityManager();
EntityTransaction tx = em.getTransaction();
tx.begin();
em.persist(account);
tx.commit();
em.close();
}
Remove an Entity
y using
g BMP
Can not delete objects in a detached state
Must programmatically merge before calling remove
@PersitenceUnit(unitName="BankApp")
Entit ManagerFactor emf;
EntityManagerFactory
emf
public void deleteAccount(Account account) {
EntityManager em = emf.createEntityManager();
EntityTransaction tx = em.getTransaction();
em getTransaction();
tx.begin();
em remove(account);
em.remove(account);
tx.commit();
em close();
em.close();
}
Find an Entity
y in CMT
No need to cast when using JPA methods
Hibernate needs to support older jdks
@PersistenceContext
@P
i t
C t t
EntityManager em;
public Account getAccount(int accountId) {
Account account =
em.find(Account.class, accountId);
return account;
}
JPA Lifecycle
y
if not
persisted
Transient
new
Removed
save()
upon Entity
Manager
closure
saveOrUpdate()
persist()
delete()
merge()
remove()
()
get()
load()
Persistent
e s ste t
find()
evict()
update()
close()
saveOrUpdate()
merge()
g ()
clear()
Detached
if not reattached
Garbage
Associations
Associations realized through orm.xml mapping
file or multiplicity annotations
javax.persistence.OneToOne
javax.persistence.OneToMany
javax.persistence.ManyToOne
javax.persistence.ManyToMany
The many
y side of many-to-one
y
bidirectional relationships
p mayy not
define the mappedBy attribute
No ID Bag support
Supports
pp
M:M,, but the relationshipp table can not have its own
primary key
Must use an intermediate class using two 1:M
orm.xml Mapping
pp g File
<entity class="Account" access="FIELD">
...
<attributes>
<id name="accountId">
<column name="ACCOUNT_ID" />
<generated-value
<generated
value strategy
strategy="AUTO"
AUTO />
</id>
<basic name="balance" optional="false">
<column name="BALANCE" />
</basic>
<version name="version">
<column name="VERSION" />
</version>
<
<one-to-many
t
name="ebills"
" bill " mapped-by="account">
d b "
t">
<join-column name="ACCOUNT_ID" />
</one-to-many>
</attributes>
Indicates the attribute on the
</entity>
corresponding association.
i.e., each ebill in the set has
an attribute called account
Bidirectional Association
@Entity
public class Account {
@OneToMany(mappedBy="account")
private Set ebills;
...
}
@Entity
public class EBill {
@ManyToOne
@JoinColumn(name="ACCOUNT_ID")
private Account account
...
}
Cascading
g
Achieved through the "cascade" attribute on the
multiplicity annotation
Multiple cascading options
Persist
Does not cascade detached or transient objects!
Merge
Remove
Refresh
All
save-update
delete
lock
evict
delete-orphan
Cascade in Mapping
pp g File
<entity class="Account" access="FIELD">
...
<attributes>
<id name="accountId">
<column name="ACCOUNT_ID" />
<generated-value
<generated
value strategy
strategy="AUTO"
AUTO />
</id>
<basic name="balance" optional="false">
<column name="BALANCE" />
</basic>
<version name="version">
<column name="VERSION" />
</version>
<
<one-to-many
t
name="ebills"
" bill " mapped-by="account">
d b "
t">
<join-column name="ACCOUNT_ID" />
<cascade>
<cascade-remove />
</cascade>
</one-to-many>
</attributes>
</entity>
Inheritance
Three ways of handling inheritance
Single table per class hierarchy
InheritanceType.SINGLE_TABLE
Table
T bl per concrete entity
i class
l
InheritanceType.TABLE_PER_CLASS
join
join strategy,
strategy where fields or properties that are
specific to a subclass are mapped to a different
properties
p
that are
table than the fields or p
common to the parent class
InheritanceType.JOINED
Mi
Missing
i Hibernates
Hib
t Implicit
I li it
Polymorphism
Single
g table per
p class hierarchy
y
Default strategy
Used if the @Inheritance annotation is not specified on
the root class of the entity hierarchy
SINGLE_TABLE
_
in Mapping
pp g File
...
<package>courses.hibernate.vo</package>
<entity class=
class="Account"
Account access=
access="FIELD">
FIELD >
<table name="ACCOUNT" />
<inheritance strategy="SINGLE_TABLE" />
<discriminator-column name="ACCOUNT_TYPE"
discriminator t pe "STRING" />
discriminator-type="STRING"
<attributes>
<id name="accountId">
<column name="ACCOUNT_ID" />
<generated-value strategy="AUTO" />
</id>
<basic name="balance" optional="false">
<column name="BALANCE" />
</basic>
<version name="version">
<column name="VERSION" />
</version>
<attributes>
</entity>
...
SINGLE_TABLE
_
in Mapping
pp g File
...
<entity class="CheckingAccount" access="PROPERTY">
<discriminator-value>CHECKING</discriminator-value>
<attributes>
<basic name="checkStyle" optional="false">
<column name="CHECK_STYLE" />
</basic>
</attributes>
</entity>
...
</entity-mappings>
Table p
per concrete entity
y class
One table for each concrete
subclass
Support for this strategy is
optional, and may not be
supported by all Java Persistence
API providers
The
Th default
d f lt JJava P
Persistence
it
API provider
id
in the Application Server does not support
thi strategy
this
t t
TopLink
join
j
strategy
gy
Super
p class has a table,, and each
subclass has a separate table
containing its specific fields
Some Java Persistence API
providers require a discriminator
column in the table that
corresponds to the root entity
Including the default provider in the
A li i Server
Application
S
join
j
strategy
gy
@Entity
@Inheritance(strategy=JOINED)
@Table(name = "ACCOUNT")
@DiscriminatorColumn(name = "ACCOUNT_TYPE",
discriminatorType = DiscriminatorType.STRING,
length = 10)
public class Account {
@Id
long accountId;
...
}
@Entity
@Table(name = "CHECKING_ACCOUNT")
@DiscriminatorValue("CHECKING")
public class CheckingAccount
p
g
extends Account {
String checkStyle;
...
}
Mapped
pp Super
p Class
Not quite implicit polymorphism, but
similar
p class attributes in
Persist super
subclasses
Mark super class with the "MappedSuperclass"
annotation
Data inherited from super classes that are not
marked
k d will
ill NOT BE PERSISTED
Mapped
pp Super
p Class
@MappedSuperclass
public class Account {
@Id
long accountId;
D t creationDate;
Date
ti D t
...
}
@Entity
@Table(name = "CHECKING_ACCOUNT")
public class CheckingAccount extends Account {
String checkStyle;
...
}
Conversations in Java SE
In Hibernate, accomplished by using
the same Hibernate Session
throughout the request
session.getCurrentSession();
No equivalent in JPA
Always have to call emf.createEntityManager();
Troublesome if a request
q
spans
p
across
multiple application DAO methods
Each method obtains an EntityManager
y
g and
commits/closes
Potential Solutions
Create the EntityManager at the instance
l
level
l off the
h DAO
Doesnt solve crossDAO situations
JPA Query
y Language
g g
Subset of Hibernate Query Language
Same syntax
Provides the @
@NamedQuery
y and
@NamedNativeQuery annotations
pp
the following:
g
Does not support
Updating the version of an entity with the
versioning keyword
Some batch functionality
insert...select statements
ScrollableResults with cursors
Additional syntactical functions available in HQL
Named Query
y Annotations
import javax.persistence.*;
@NamedQueries( {
@NamedQuery(
name = "getAllAccounts"
query = "from Account")
@NamedQuery(
name = "getAccountByBalance"
query = "from Account where
balance = :balance")
})
CURRENT_DATE(), CURRENT_TIME(),
CURRENT_TIMESTAMP()
Returns
R t
th
the currentt value
l off the
th database
d t b
machine
hi
CAST(t as Type)
Casts a given type t to a Hibernate Type
INDEX(joinedCollection)
Returns the index of a joined collection element
MINELEMENT((c),
), MAXELEMENT(c),MININDEX(c),
( ),
( ),
MAXINDEX(c), ELEMENTS(c), INDICES(c)
Returns an element or index of an indexed collection
@PrePersist; @PostPersist
Executes immediately when persist() is called, and after
the database insert respectively
@
@PreUpdate;
p
; @PostUpdate
@
p
Executes immediately before and after flushing, and only
for dirty objects
@PreRemove; @PostRemove
Executes immediately when remove() is called or removed
via a cascade, and after the database delete respectively
Creating
g a Listener
import javax.persistence.*;
// no special interface or superclass
public class AccountListener {
@PostPersist
public void accountCreation(Object entity) {
logger info("Account Created: " + entity);
logger.info("Account
}
}
Assigning
g
g the Listener Callback
import javax.persistence.*;
@Entity
@EntityListeners(AccountListener.class)
public class Account {
public void saveAccount(Account account) {
...
}
}
JPA Benefits
Automatic scanning of deployed
metadata
g
Standardized configuration
Persistence Unit
JPA Disadvantages
g
Though standard interfaces are nice, some-what
lenient spec may
ma present gaps when
hen switching
s itching
vendor implementations
Not all inheritance strategies supported
Standardized descriptor file is basically a wrapper around vendor
specific implementations
Hibernate Documentation
jpa.hibernate.org/
2009 coreservlets.com
Wrap-up
Customized Java EE Training: http://courses.coreservlets.com/
Servlets, JSP, Struts, JSF/MyFaces/Facelets, Ajax, GWT, Spring, Hibernate/JPA, Java 5 & 6.
Developed and taught by well-known author and developer. At public venues or onsite at your location.
Summary
y
In this lecture, we:
Learned about the JSR-220 intentions, and how it
came about to develop the Java Persistence API
S ifi i
Specification
Walked through the main components of JPA
Pointed
P i t d outt its
it advantages
d t
andd disadvantages
di d t
when compared to a vendor specific
implementation like Hibernate
implementation,
Setup and configured Hibernate to serve as our
p
JPA providers
64
2009 coreservlets.com
Q
Questions?
ti
?
Customized Java EE Training: http://courses.coreservlets.com/
Servlets, JSP, Struts, JSF/MyFaces/Facelets, Ajax, GWT, Spring, Hibernate/JPA, Java 5 & 6.
Developed and taught by well-known author and developer. At public venues or onsite at your location.