Java Persistence API
Agenda- Overview- OR Mapping and Entity Introduction- Entity Manager- Transactions- Persistence Context- Relationships- Query Capabilities- Criteria
So, what's the big deal ?- Relational DB and Java are world apart- JDBC
- Mandates manual marshaling- SQL Queries are difficult to manage
- No compile time support- Boiler plate- Database portability
- EJB 2.1- Beast- Horrible to work with
- Need of the hour : Lightweight POJO framework
What we need to save the day ?- Higher level abstraction above JDBC- Provide object view of RDBMS resources- Simple to configure- Lightweight- Unobtrusive- Local, but Mobile- Integration and Testability- Above all, Fun to work with
JPA- All of the items listed in prev slide and ...- Feature rich - Spec is about 500+ pages- More than one way to do, that way looks complex- Can be used in JavaEE as well as JavaSE environments- Wait, we do have alternatives
- Data Mapper- Java Data Objects- JDBC
History- JPA 1.0 (2006)
- Part of EJB 3.0 Spec- Start over (Leaving Legacy Entity framework)- Leading ORM experts on the panel (Hibernate, TopLink, etc)
- JPA 2.0 (2009)- Added significant amount of features to catch up with ORM vendors- Criteria API- Bean Validation- Metamodel
- JPA 2.1 (2013)- Converters- Criteria Update/Delete- Stored Procedures
Big Players- Client- JPA Spec API- JPA implementation
- Hibernate- EclipseLink (prev TopLink)- Apache OpenJPA
- Database Driver- DB
- App Level : <persistence-unit>- DB location : JNDI or DB URL- List of Entity classes- JPA provider : Hibernate
- Each Entity Class- Table name- Column names
- Client that uses JPA API
Code / Configuration
Lab - 1 - Module Setup- Step 1 : Create a git repo- Step 2 : Create a maven module (all defaults)- Step 3 : Git commit- Step 4 : Add Dependencies
- Client (JUnit)- JPA Spec API- Hibernate Core- Entity Manager- Database driver jar
- Step 5 : Add JPA configuration file : persistence.xml- Step 6 : Assert em.isOpen()- Step 7 : Git commit
OR Mapping- Class <-> Table
- Property <-> Column- Properties without mapping to any column : Transient
- Instance of Class <-> Row in the table- Relies on Convention over Configuration- Same old POJO underneath- Entities are still EJBs ? Yes and No !
- Typically created with new operator- Like SBs to container, Entities to EntityManager- Resides on server but client directly interacts with them unlike EJB siblings
- Can define DB schema (not for production use)
Lab - 2 : Find Employee- Step 1 : Employees Entity- Step 2 : persistence.xml using MySQL Employees DB- Step 3 : Assert employee presence- Step 5 : Getters and Setters- Step 6 : Updated test run
Object-Relational Mapping- POJO needs something to become Entity- 2 Ways : Annotations or XML- Two types of Annotations
- Logical - Describes object model- @Entity, @Basic, @Temporal etc.
- Physical - Describes physical schema- @Table, @Column etc.
- Configuration by Exception- Optional (Almost)- Can be specified on Fields or Bean Properties- Field annotations : Getters/Setters ignored- Bare minimum : @Entity and @Id annotations
Mapping simple types- Java Primitive types and Wrappers- Byte[], Byte[], char[], Character[]- java.lang.String- java.math.BigInteger, BigDecimal- java.util.Date, Calendar- java.sql.Date, Time, Timestamp- Enums
Entity, Who are you ?- Entity must have an identity- Annotate the field with @Id- Equivalent of primary key
- Primary key not mandatory in DB table- Multiple rows with same value in @Id mapped column. Trouble!
- Composite primary key- @IdClass- @EmbeddedId- @MapsId
ID Generation- 4 Types
- AUTO- For prototyping only
- IDENTITY- SEQUENCE- TABLE
- DB agnostic
- IDENTITY and SEQUENCE need DB support
Serializable Entities- Not mandated by Spec- Application can opt for when
- Entities are shared across VMs- Entities are stored in (clustered/serialized) sessions
Entity LIfecycle
Source
JPA Key ElementsPersistence
Source
EntityManagerFactory
Persistence Context
Persistence Unit (Tangible)- Named configuration of entity classes
EntityManager (Tangible)- Central authority- Qualifies simple POJOs into Entities- Almost entire API is built in this one interface- Provides API to
- Do CRUD- Query- Synchronize with Database
- Automatically sync to DB- 1st Level Caching- Works with JTA in server env
EntityManager (Tangible)- Obtained from EntityManagerFactory- Not thread-safe and must not be shared between threads- Java EE
- Can be obtained directly using CDI injection or JNDI lookup- Typically a transaction involves multiple components- Need same entity context all through the transaction- Multiple entity managers (within a tx) automatically points to same Persistence Context- We don't have to pass reference of EntityManager between calls
- Java SE- Using standalone bootstrap class Persistence- Each call to emf.createEntityManager() creates a new isolated persistence context
Persistence Context (Intangible)- Invisible- A set of managed Entity objects- Associated to a Persistence Unit- Managed by one or more EntityManagers- Only one Entity with same identity- Entities contained within are “managed”
Source
Transaction- ACID- Transaction Demarcation : Act of beginning or completing- JPA supports two types
- Resource Local- JavaSE and JavaEE (without container support) applications- Always application demarcated
- JTA- aka Global Transactions- Spans across resources (multiple DBs, Messaging server, etc…)- Demarcated by containers (most of the times)
Transaction Contd...
- Transaction Synchronization : Process by which a persistence context is registered with a transaction
- Transaction Association : Act of binding a persistence context to a transaction- Transaction Propagation : Process of sharing a persistence context between
multiple entity managers within a transaction
Entity Manager Types- EntityManager can be
- Container Managed Transaction-scoped- Container Managed Extended- Application scoped
- Scope is defined when the EntityManager is created
Container Managed Entity Manager- Mostly we are talking about Java EE environment- Injected via @PersistenceContext- No need to Open or Close it- Two flavors
- Transaction Scoped- Extended
Transaction Scoped- Default- Lives as long as Transaction is alive- Once transaction finished, all objects are detached- Lazily created : When an operation on EntityManager is called- @PersistenceContext hands over a proxy- Stateless- Maintenance free
Transaction Scoped Contd...
- Gets associated to the ongoing transaction seamlessly
Transaction Scoped Contd...
Extended Context- Meant for @Stateful beans only- Begins with EM creation and live till its closed- Eagerly created : As soon as the txn begins- The context gets destroyed when @Remove on SFSB is called- Extended spans transactions and manages Entities between Txns- Caching of Entity is not the objective but mostly you will be doing it
Extended Context- Prevents Entities from becoming detached when txn ends- Client can use bean fields to hold state and interact with DB
Extended Contd...
Application managed Context- Mostly Java SE environments- Can be used in Java EE Environment as well- Application is responsible for context’s life cycle- Extended by nature and spans multiple transactions- Needs Explicit
- Creation : EntityManagerFactory.createEntityManager()- Flushing/Closing : EntityManager.close()
- Is standalone and not propagated with transaction- Can join transaction by EntityManager.joinTransaction()- Typically used in Unit Testing
Recommendations- Stateless Beans
- Preferred way to manage persistence operations- Use @PersistantContext to inject EntityManager
- Stateful Beans- Extended context- State can include EntityContext and its result data
- Use JNDI lookup to get Stateful beans (no @Inject/@EJB)- In case of rollback, DO NOT revive the detached object
Caching- Concept is to avoid going to DB by maintaining an in-sync object in memory- Entity Manager serves as 1st level cache- Infinispan is default for WildFly- Caching hurdles
- In memory objects are not transactional- Data sync with Database- Memory occupancy
Relationships in DB- Achieved via
- Foreign Key- Mapping tables
- Table with Foreign Key column is the owner
A bit insights into DB
Relationships- No Entity is an Island!- Table with foreign key always ends up with single association- Roles
- Employee “works in” a Department- Department “has” employees working in it- One Entity can participate in many relationships
- Directionality- Unidirectional- BiDirectional
-
Relationships Cntd...
- Cardinality- One to One- One to Many- Many to One- Many to Many
- Ordinality (aka Optionality)
Relationships Myths- Way to avoid business logic
- You still have to deal with CascadeType
- Gives flexibility- Too little for too much price- Lazy Vs Eager loading- OpenEntityManagerInViewFilter
- Shields developer from database- To very little extent- Often the cause for killer bugs/defects
-
Single Valued Associations- Cardinality of Target entity is 1
- ManyToOne- OneToOne
- ManyToOne - Rules- @JoinColumn goes in Entity that has foreign key defined- @ManyToOne goes into the owning side i.e with foreign key- @OneToMany(mappedBy) goes into the target Entity in case of Bidirectional
- OneToOne - Two Rules- @JoinColumn goes in Entity that has foreign key defined- @OneToOne(mappedBy) goes into the target Entity in case of Bidirectional
-
Many To One- Always Source has has attribute of Target type- Enables navigation from Source to Target- @ManyToOne and @JoinColumn- Table with foreign key is owning side- Ownership is important because of foreign key column- @JoinColumn is specified on the owning side- Many to One mappings are always on owning side
Many To One- @JoinColumn is optional- Default join column : targetTable_targetIdColumn- @Column won’t gel with these annotations
One To One- Almost similar to Many To One- @OneToOne and @JoinColumn- Table with foreign key is the owning side- @JoinColumn has to be on the side with foreign key
One To One Bidirectional- Source Entity already has all the information- It just needs which property on source entity has it- @OneToOne(mappedBy)
Collection Valued Associations- Source entity references one or more Target entities
- OneToMany- ManyToMany
One To Many- Nothing but Bidirectional ManyToOne- Always implies a ManyToOne presence- Always Bidirectional- Always on the target side i.e. Not the Source side- All configuration is in Source entity already- Just needs the Source entity property information- @OneToMany(mappedBy)
Many To Many- @JoinColumn is not sufficient- Can be achieved only by a join table- Difficult to say who is the owner- Either can be the owner- The target side will have @ManyToMany(mappedBy)- Absence of mappedBy will make them unidirectional
Many To Many Bidirectional- mappedBy on the target side- All it needs is the property configured in Source Entity
One To Many using a @TableJoin- @OneToMany is not just bidirectional @ManyToOne- Can be achieved with a @TableJoin
Lazy Relationships- Not specified, @ManyToOne and @OneToOne guaranteed to Eagerly load- Collection valued relationships by default is Lazily load- Provider may choose to do Eager loading
Queries- CRUD - Retrieval Rules- As expected, constructed using EntityManager- API
- Query- TypedQuery
- Type- Static - Annotation or XML- Dynamic
- JPQL- Criteria
- Dynamic queries are expensive
JPQL- Limited yet powerful- Metamodel is not mandatory (almost)- Limited compile time safety- Two types
- @NamedQuery- Dynamic string query
Criteria API- Programmatic control- Robust- Uses Objects instead of Strings- Can result in bloated code- More than One way to do it- Query is prepared dynamically- Allows flexible filtering
Criteria Query - Entity Result
References- JPA 2.1 Specification (Not for humans)- JPA 2.1 Java Doc (Amazingly small)- (Blog) JPA 2.1 – 12 features every developer should know- MySQL Employees Sample DB
Top Related