Java Persistence Java API - hornad.fei.tuke.skporuban/wt/JPA.pdf · JavaTM Persistence Context...
Transcript of Java Persistence Java API - hornad.fei.tuke.skporuban/wt/JPA.pdf · JavaTM Persistence Context...
JavaTM Java Persistence API
Jaroslav Porubän, Peter Václavík2008
JavaTM
What is an Entity?
Models real-world object Plain Old Java Object (POJO)
No required interfaces, superclasses Has a persistence identity May have both persistent and non-
persistent state Non-persistent state (transient or
@Transient) Can extend other entity and non-
entity classes
JavaTM
Persistence Context
Represents a set of managed entity instances at runtime “Entity instance is in managed state” means
it is contained in a persistent context Not directly accessible to an application
Managed by an entity manager When a persistence context is closed, all
managed entity objects become detached and are unmanaged
JavaTM
Persistence Context Configuration
Persistence context is defined in a persistence.xml file This file is a required deployment descriptor
for the Java Persistence specification A persistence.xml file can define
one or more persistence units Persistence unit is tied to one and only one
data source Specifies set of classes defining mapping to a
particular database
JavaTM
Persistence Context Configuration Example<persistence> <persistence-unit name="shop"> <jta-data-source>java:/ShopDB </jta-data-source>
<class>examples.shop.Customer</class><class>examples.shop.Product</class><properties>
<property name="hibernate.show_sql" value="true"/> </properties> </persistence-unit></persistence>
JavaTM
Entity Manager
Is the central service for all persistence actions
Performs life-cycle operations on entities
Manages the O/R mapping between a fixed set of entity classes and an underlying data source
You can use Java Persistence outside of an application server in plain Java SE programs
JavaTM
Entity Manager API
Creating queries Finding objects Synchronizing objects Inserting objects into the database Providing caching Managing the interaction between
an entity and transactional services in a Java EE environment such as JTA
JavaTM
Entity Manager Injection
An EntityManager can be injected directly into an EJB using the @PersistenceContext annotation
@Statelesspublic class MySessionBean implements
MySessionRemote { @PersistenceContext(unitName="shop") private EntityManager entityManager;
...}
JavaTM
Entity Life Cycle
JavaTM
Entity Manager APIpublic interface EntityManager { public void persist(Object entity); public <T> T find(Class <T> entityClass,
Object primaryKey); public <T> T getReference(Class <T> entityClass,
Object primaryKey); public <T> T merge(T entity); public void remove(Object entity); public void lock(Object entity,
LockModeType lockMode);
public void refresh(Object entity); public boolean contains(Object entity); public void clear( );
public void joinTransaction( ); public void flush( );...continues on next page
JavaTM
Entity Manager API... from previous page
public FlushModeType getFlushMode( ); public void setFlushMode(FlushModeType type);
public Query createQuery(String queryString); public Query createNamedQuery(String name); public Query createNativeQuery(String sqlString); public Query createNativeQuery(String sqlString,
String resultSetMapping); public Query createNativeQuery(String sqlString,
Class resultClass);
public Object getDelegate( );
public void close( ); public boolean isOpen( );}
JavaTM
Entity Manager: Entity Life Cycle Management
Similar in functionality to Hibernate Session, JDO PersistenceManager, etc.
Life cycle methods: persist() - insert an entity into the DB remove() - remove an entity from the DB merge() - synchronize the state of
detached entities refresh() - reloads state from the
database
JavaTM
Entity Manager: Other Entity Management Methods
Finding entities: find()
Queries: createQuery(), createNamedQuery(),
createNativeQuery() Synchronizing entities with database:
flush() Other methods:
contains(), clear()
JavaTM
Finding Entities Example
Method find()MyEntity e = entityManager.find(MyEntity.class,2);
JavaTM
Persisting Entities
Persisting entities that have not yet been created in the database Queues object for insertion into the database Insert may happen immediately
Depending on a flush mode
The object instance becomes managed If the entity has any relationships with
other entities, these entities may also be created within the database if you have the appropriate cascade policies
JavaTM
Persisting Entities ExampleEntityManager entityManager;...MyEntity e = new MyEntity();...entityManager.persist(e);
JavaTM
Removing Entities
The remove() operation does not immediately delete the entity from the database
After remove() is invoked, the removed object will no longer be managed If the entity has any relationships to
other entity objects, those may also be removed depending on the cascading rules
JavaTM
Removing Entities Exampleprivate EntityManager entityManager;...public void removeMethod(long id) { SomeEntity e = entityManager.find(SomeEntity.class,id); entityManager.remove(e);}
JavaTM
Merging Entities The merge() method merge state
changes made to a detached entity back into persistence storage
The merge() method returns a managed copy of the given detached entity
public MyEntity updateOrderLine(MyEntity e){ return entityManager.merge(e);}
JavaTM
Refreshing Entities
Managed entity will be up-to-date with the database
The refresh() method refreshes the state of the entity from the database Overwriting any changes made to that entity
If the entity bean has any related entities, those entities may also be refreshed, depending on the cascade policy
JavaTM
Refreshing Entities Examplepublic void someMethod(int id) { SomeClass obj = entityManager.find(SomeClass.class, id);
...
//The state of the entity from the database //overwriting any changes made to that //entity
entityManager.refresh(obj);}
JavaTM
Queries
Persistent objects can be located by using JPQL or native SQL
You must create a Query object by calling methods: createQuery() – dynamically
created EJB QL query createNamedQuery() – statically
created EJB QL query createNativeQuery() – native
SQL query
JavaTM
Named Query Example @NamedQuery(name = "findUser",
query = "SELECT c FROM Customer c WHERE c.login = :custName")
@Entitypublic class Customer {…}
public Customer getUser(String login) { Query q = manager.createNamedQuery("findUser"); q.setParameter("custName", login); return (Customer)q.getSingleResult(); }
JavaTM
Query Example String condition = "where id=2";...//You can modify condition ...Query query = entityManager.createQuery("from Customer c " + condition);
Customer cust = (Customer)query.getSingleResult();
JavaTM
Updating Entity Example
public void updateMethod(int id, int newVal) { SomeClass c = entityManager.find(SomeClass.class, id); c.setValue(newVal);}
JavaTM
Java Persistence Programming Model
Persistence is the process of coordinating the data represented by a bean instance with the database
Entity is a POJO (no need to implement Enterprise Entity Bean)
Java Persistence API can automatically map your Java objects to and from a relational database (ORM)
Using of annotation to denote a POJO as an entity (instead of deployment descriptor)
JavaTM
Java Persistence Programming Model Example
@Entity public class MyEntity { // Persistent/transient fields // Property accessor methods // "Persistence logic" methods}
JavaTM
Entity Example @Entity public class Customer { private long id; private Collection<Order> orders = new HashSet(); ...
@Id public long getID() { return id; } protected void setID(long id) { this.id = id; }
Annotated as entity
@Id denotes primary key
Getters/setters to access state
JavaTM
Entity Example ...
@OneToMany public Collection<Order> getOrders() { return orders; }
public void setOrders( Collection<Order> orders) { this.orders = orders; }
// Other persistence methods}
Relationship between Customer and Order
JavaTM
O/R Mapping
A developer can take two directions when implementing entity beans: Derive a database schema from a Java
object model Derive a Java object model from
existing database schema Specified using
Annotations within the code Separate mapping file
JavaTM
Simple Mapping
public class Customer { int id; String name; int c_rating; Image photo;}
@Entity(access=FIELD)
@Column(name=“CREDIT”)
@Id
@Lob
CUSTOMERID NAME CREDIT PHOTO
JavaTM
Primary Key Primary key is the identity of a given
entity bean Every entity bean must have a primary
key, and it must be unique Primary keys can map to one or more
properties Primary keys must map to one of the
following types: Any Java primitive type (including wrappers) java.lang.String Primary-key class composed of primitives
and/or strings
JavaTM
@Id Generating the primary key:
Manually Using persistence provider -
@GeneratedValue annotation @GeneratedValue annotation
GeneratorType.AUTO – default GeneratorType.TABLE GeneratorType.SEQUENCE
GeneratorType. IDENTITY
JavaTM
Property Mappings
@Transient @Basic @Temporal @Lob @Enumerated
JavaTM
@Transient Persistence manager would assume that
every nontransient property in your bean class is persistent
Properties annotated with @Transient annotation persistence manager ignores and doesn't treat it as persistent
JavaTM
@Basic It is the simplest form of mapping
for a persistent properties of primitives and primitive wrapper types
Attribute fetch() specify whether a particular property is loaded lazily or eagerly when the persistent object is first fetched from the database FetchType.LAZY FetchType.EAGER - default
JavaTM
@Basic@Entitypublic class Customer implements java.io.Serializable { ... @Basic(fetch=FetchType.LAZY,optional=false) public String getFirstName() { return firstName; } public void setFirstName(String firstName){ this.firstName = firstName; } ... }
JavaTM
@Temporal Provides additional information to the
persistence provider about the mapping of a java.util.Date or java.util.Calendar property It allows to map these object types to a
date, a time, or a timestamp field in the database
Temporal types: TemporalType.DATE TemporalType.TIME TemporalType.TIMESTAMP - Default
JavaTM
@Temporal@Entitypublic class Customer implements java.io.Serializable { private java.util.Date timeCreated; ...
@Temporal(TemporalType.TIME) public java.util.Date getTimeCreated( ) { return timeCreated; } public void setTimeCreated( java.util.Date time) { timeCreated = time; }}
JavaTM
@Lob If persistent properties require a lot of
memory, for example: Images - java.sql.Blob Large text documents - java.sql.Clob
It is usually used in conjunction with the @Basic annotation to hint that the property should be lazily loaded
Properties annotated with a @Lob: Blob if the Java type is byte[], Byte[], or
java.io.Serializable Clob if the Java type is char[],
Character[], or java.lang.String
JavaTM
@Lobimport com.acme.imaging.JPEG;
@Entitypublic class Customer implements java.io.Serializable { private JPEG picture;
... @Lob @Basic(fetch=FetchType.LAZY) public JPEG getPicture( ) { return picture; } public void setPicture(JPEG picture) { this.picture = picture; }}
JavaTM
@Enumerated Maps Java enum types to the
database A Java enum property can be
mapped to: String representation
EnumType.STRING Numeric ordinal number
EnumType.ORDINAL - default
JavaTM
@Enumerated@Entitypublic class Customer implements java.io.Serializable { public enum CustomerType { UNREGISTERED, REGISTERED } private CustomerType customerType;
@Enumerated(EnumType.STRING) public CustomerType getCustomerType() {...} public void setCustomerType(CustomerType t) { ... }}
JavaTM
Entity Relationships
Models association between entities Supports unidirectional as well as
bidirectional relationships Unidirectional relationship: Entity A
references B, but B doesn't reference A Cardinalities:
One to one One to many Many to one Many to many
JavaTM
Cascading Behavior Cascading is used to propagate the effect
of an operation to associated entities Cascading can be applied to:
persist() merge() remove() refresh()
Cascading operations will work only when entities are associated to the persistence context Otherwise IllegalArgumentException
is thrown
JavaTM
Cascading Behavior
CascadeType.PERSIST deals with the creation of entities within the database
CascadeType.REMOVE deals with the deleting of entities within the database
CascadeType.MERGE deals with entity synchronization, meaning updates
CascadeType.REFRESH refreshes the object instance's state from the database
CascadeType.ALL Represents all of the cascade operations
JavaTM
One-to-One Unidirectional Relationship
CUSTOMER
ID INT PRIMARY KEY
FIRST_NAME CHAR(20)
LAST_NAME CHAR(20)
ADDRESS_ID INT
1 O:1
ADDRESS
ID INT PRIMARY KEY
CITY CHAR(20)
STATE CHAR(20)
ZIP CHAR(10)
STREET CHAR(40)
JavaTM
One-to-One Unidirectional Relationship@Entitypublic class Customer implements java.io.Serializable { ... private Address address; ... @OneToOne(cascade={CascadeType.ALL}) @JoinColumn (name="ADDRESS_ID") public Address getAddress() { return address; } public void setAddress(Address address) { this.address = address; }
JavaTM
One-to-One Bidirectional Relationship
1 O:1
CUSTOMER
ID INT PRIMARY KEY
FIRST_NAME CHAR(20)
LAST_NAME CHAR(20)
ADDRESS_ID INTCREDIT_CARD_ID INT
CREDIT_CARD
ID INT PRIMARY KEY
NUMBER CHAR(20)
NAME CHAR(4)
ORGANIZATION CHAR(20)
EXP_DATE DATE
JavaTM
One-to-One Bidirectional Relationship@Entitypublic class Customer implements java.io.Serializable { private CreditCard creditCard; ... @OneToOne (cascade={CascadeType.ALL}) @JoinColumn(name="CREDIT_CARD_ID") public CreditCard getCreditCard( ) { return creditCard; } public void setCreditCard(CreditCard card) { this.creditCard = card; } ...}
JavaTM
One-to-One Bidirectional Relationship@Entitypublic class CreditCard implements java.io.Serializable { private Customer customer; ... //Mapping is specified in creditCard //property of Customer bean class @OneToOne(mappedBy="creditCard") public Customer getCustomer( ) { return this.customer; } public void setCustomer(Customer customer) { this.customer = customer; }}
JavaTM
One-to-One Bidirectional Relationship
With all bidirectional relationship types, including one-to-one, there is always the concept of an owning side of the relationship
Used mappedBy attribute designated the CreditCard entity as the inverse side of the relationship Customer entity is the owning side of
the relationship
JavaTM
One-to-One Bidirectional Relationship
Setting up a bidirectional relationship:
Customer cust = new Customer();CreditCard card = new CreditCard();cust.setCreditCard(card);card.setCustomer(cust);entityManager.persist(cust);
JavaTM
One-to-One Bidirectional Relationship
Always wire both sides of a bidirectional relationship when modifying relationships
If you wanted to associate a CreditCard instance with a different Customer:
Customer newCust = em.find(Customer.class, newCustId);CreditCard card = oldCustomer.getCreditCard();oldCustomer.setCreditCard(null);newCust.setCreditCard(card);
JavaTM
One-to-Many Unidirectional Relationship
1 O:M
CUSTOMER
ID INT PRIMARY KEY
FIRST_NAME CHAR(20)
LAST_NAME CHAR(20)
ADDRESS_ID INTCREDIT_CARD_ID INT
PHONE
ID INT PRIMARY KEY
TYPE INT
CUSTOMER_ID INT
NUMBER CHAR(20)
JavaTM
One-to-Many Unidirectional Relationship@Entitypublic class Customer implements java.io.Serializable { ... private Collection<Phone> phoneNumbers= new ArrayList<Phone>(); ... @OneToMany(cascade={CascadeType.ALL}) @JoinColumn (name="CUSTOMER_ID") public Collection<Phone> getPhoneNumbers() {…} public void setPhoneNumbers(Collection<Phone> phones) {…}}
JavaTM
One-to-Many Unidirectional Relationship
Let's look at some code:Customer cust = entityManager.find(Customer.class, pk);Phone phone = new Phone("617-333-3333", 5);cust.getPhones().add(phone);
The new Phone will automatically be created in the database
If you need to remove a Phone from the relationship, you need to remove the Phone from both the collection and the database:
cust.getPhones().remove(phone);entityManager.remove(phone);
JavaTM
Many-to-One Unidirectional Relationship
CRUISE
ID INT PRIMARY KEY
NAME CHAR(30)
SHIP_ID INT
SHIP
ID INT PRIMARY KEY
TONNAGE DECIMAL(8,2)
NAME CHAR(30)
1O:M
JavaTM
Many-to-One Unidirectional Relationship@Entitypublic class Cruise implements java.io.Serializable { private Ship ship; ... @ManyToOne @JoinColumn (name="SHIP_ID") public Ship getShip() { return ship; } public void setShip(Ship ship) { this.ship = ship; }}
JavaTM
One-to-Many Bidirectional Relationship
CRUISE
ID INT PRIMARY KEY
NAME CHAR(30)
SHIP_ID INT
1 O:M
RESERVATION
ID INT PRIMARY KEY
DATE_RESERVED DATE
AMOUNT_PAID DECIMAL(8,2)
CRUISE_ID INT
JavaTM
One-to-Many Bidirectional Relationship@Entitypublic class Reservation implements java.io.Serializable { private Cruise cruise; ... @ManyToOne @JoinColumn(name="CRUISE_ID") public Cruise getCruise( ) { return cruise; } public void setCruise(Cruise cruise) { this.cruise = cruise ; }}
JavaTM
One-to-Many Bidirectional Relationship@Entitypublic class Cruise implements java.io.Serializable { private Collection<Reservation> reservations = new ArrayList<Reservation>(); ... @OneToMany(mappedBy="cruise") public Collection<Reservation> getReservations(){ return reservations; } public void setReservations( Collection<Reserveration> res) { this.reservations = res; }}
JavaTM
Many-to-Many Unidirectional Relationship
RESERVATION
ID INT PRIMARY KEY
DATE_RESERVED DATE
AMOUNT_PAID DECIMAL(8,2)
CRUISE_ID INT
CABIN
ID INT PRIMARY KEYSHIP_ID INTNAME CHAR(10)DECK_LEVEL INTBED_COUNT INT
CABIN_RESERVATION
RESERVATION_ID INT
CABIN_ID INT
1 O:M
1
O:M
JavaTM
Many-to-Many Unidirectional Relationship@Entitypublic class Reservation implements java.io.Serializable { ... @ManyToMany @JoinTable(name="CABIN_RESERVATION", joinColumns={@JoinColumn( name="RESERVATION_ID")},
inverseJoinColumns={ @JoinColumn(name="CABIN_ID")}) public Set<Cabin> getCabins( ) {...} public void setCabins(Set<Cabin> cabins) { this.cabins = cabins; } ...
JavaTM
Many-to-Many Bidirectional Relationship
RESERVATION
ID INT PRIMARY KEY
DATE_RESERVED DATE
AMOUNT_PAID DECIMAL(8,2)
CRUISE_ID INT
CUSTOMER _RESERVATION
RESERVATION_ID INT
CUSTOMER_ID INT
1 O:M
1
O:M
CUSTOMER
ID INT PRIMARY KEY
FIRST_NAME CHAR(20)
LAST_NAME CHAR(20)
ADDRESS_ID INTCREDIT_CARD_ID INT
JavaTM
Many-to-Many Bidirectional Relationship@Entitypublic class Reservation implements java.io.Serializable { private Set<Customer> customers = new HashSet<Customer>(); ... @ManyToMany @JoinTable (name="RESERVATION_CUSTOMER"), joinColumns={ @JoinColumn(name="RESERVATION_ID")}, inverseJoinColumns={ @JoinColumn(name="CUSTOMER_ID")}) public Set<Customer> getCustomers( ) {...} public void setCustomers(Set customers) {...} ...}
JavaTM
Many-to-Many Bidirectional Relationship@Entitypublic class Customer implements java.io.Serializable { private Collection<Reservation> reservations = new ArrayList<Reservation>( ); ... @ManyToMany(mappedBy="customers") public Collection<Reservation> getReservations(){ return reservations; } public void setReservations( Collection<Reservation> reservations) { this.reservations = reservations; } ...}
JavaTM
Entity Listeners Listeners (callback methods) are
designated to receive invocations from persistence provider at various stages of entity lifecycle
PrePersist / PostPersist PreRemove/ PostRemove PreUpdate / PostUpdate PostLoad
Annotate callback handling methods right in the entity class or put them in a separate listener class
JavaTM
Entity Listener@Entity@EntityListener(com.acme.AlertMonitor.class)public class AccountBean implements Account { ... @PrePersist public void validateCreate() {...}
@PostLoad public void adjustPreferredStatus() {...}}
JavaTM
Entity Listenerpublic class AlertMonitor {
@PostPersist public void newAccountAlert(Account acct) { ... }}