jpa 2.1 application development
TRANSCRIPT
JPA 2.1JSR-338 Specification
Why JPA ?
Java Persistence API (JPA), was introduced
into the platform to bridge the gap between
object-oriented domain models and relational
database systems
API is part of javax.persistence.* package
distributed by different vendors hibernate-jpa-
2.1-api.jar
JPA Terminology Entity: It is nothing but a java representation of the database
table that should have characteristics like persist ability, identity, transactional and granularity.
Persistence Unit: Configuration of Entities and DB access information. (persistence.xml file)
EntityManagerFactory: Factory of Entity Managers which we can create by passing Persistence Unit.
EntityManager: Different API calls performed on entities are managed by the single interface called EntityManager.
PersistenceContext: Set of entities which are managed by the entity manager are called persistence context.
Persistence Provider: Provides underlying implementation to the APIs. (hibernate, eclipse link etc..)
Characteristics of an Entity
An entity class must follow these requirements.
The class must be annotated with the javax.persistence.Entity annotation.
The class must have a public or protected, no-argument constructor. The class may have other constructors.
The class must not be declared final. No methods or persistent instance variables must be declared final.
If an entity instance is passed by value as a detached object, such as through a session bean’s remote business interface, the class must implement the Serializable interface.
Entities may extend both entity and non-entity classes, and non-entity classes may extend entity classes.
Persistent instance variables must be declared private, protected, or package-private and can be accessed directly only by the entity class’s methods. Clients must access the entity’s state through accessor or business methods.
Persistence UNIT and Context
A persistence unit is a named configuration of entity classes.
A persistence context is a managed set of entity instances.
Every persistence context is associated with a persistence unit, restricting the classes of the managed instances to the set defined by the persistence unit.
Saying that an entity instance is managed means that it is contained within a persistence context and it can be acted upon by an entity manager. It is for this reason that we say that an entity manager manages a persistence context.
The entity manager type determines the lifetime of a persistence context
Entity Manager types Container Managed Entity Managers: Lifecycle of the
entity manager managed by the container. @PersistenceContext(unitName="MysqlPU")
EntityManager entityManager;
Transaction-scoped: This means that the persistence contexts managed by the entity manager are scoped by the active JTA transaction, ending when the transaction is complete.
Extended: persistence context of an extended entity manager will last for the entire length of the conversation of service (ex: stateful session bean)
Application Managed Entity Manager : application will manages the lifecycle of the entity manager.
final EntityManagerFactory emf = Persistence.createEntityManagerFactory("MysqlPU");
final EntityManager em = emf.createEntityManager();
Transaction Managers There are two types of transaction managers supported
by the JPA Resource Local : native transactions of the JDBC drivers
that are referenced by a persistence unit.
JTA: transactions of the Java EE server, supporting multiple participating resources, transaction lifecycle management, and distributed XA transactions.
Container-managed entity managers always use JTA transactions, while application-managed entity managers can use either type.
Because JTA is typically not available in Java SE applications, the provider needs to support only resource-local transactions in that environment.
The default and preferred transaction type for Java EE applications is JTA. propagating persistence contexts with JTA transactions is a major benefit to enterprise persistence applications.
Container Managed VS Application Managed EntityManager
Container Managed EntityManager
@PersistenceContext
EntityManager em;
Application Managed EntityManager
@PersistenceUnit
EntityManagerFactory emf;
Ref: http://piotrnowicki.com/2012/11/types-of-
entitymanagers-application-managed-entitymanager/
Extended Vs Transactional Scoped This feature tells us if the EntityManager’s operations might span
across multiple transactions. By default the Transactional Persistence Context is used which means that all changes are flushed and all managed entities become detached when the current transaction commits.
The extended scope is available only for Stateful EJBs; it makes perfectly sense as the SFSBs can save the state, so end of one business method doesn’t necessary means the end of the transaction.
With the SLSB the story is different – we have business method that must end when the business method finishes because in next invocation we don’t have an idea which EJB instance we’ll end in. One method = one transaction; only transactional-scoped EntityManager is allowed for SLSB.
NOTE: Extended and transaction scoped PersistenceContext are allowed only in case of container-managed EntityManagers.
JPQL (Java Persistence query Language)
It is similar to SQL queries but it refers Entity
names instead of table names.
@Entity(name="Employee")
@Table(name = "employee_tbl")
public class EmployeeEntity { }
JPQL: SELECT e FROM Employee e;
QUERY PARAMETERS
NOTATION POSITIONAL PARAMETERSfinal Query positionalParamQuery =
em.createQuery("SELECT e FROM Employee e WHERE
e.id>?1", EmployeeEntity.class);
positionalParamQuery.setParameter(1, 1600l);
NAMED PARAMETERSfinal Query namedParameterQuery =
em.createQuery("SELECT e FROM Employee e WHERE
e.id>=:id", EmployeeEntity.class);
namedParameterQuery.setParameter("id", 1700l);
Named Queries (Recommended)
Persistence providers will often take steps to precompile JPQL named queries to SQL as part of the deployment or initialization phase of an application
@Entity(name = "Employee")
@Table(name = "employee_tbl")
@NamedQuery(name = "employeeById", query = "SELECT e FROM Employee e WHERE e.id=:id")
public class EmployeeEntity {}
final Query namedQuery = em.createNamedQuery("employeeById");
namedQuery.setParameter("id", 1801l);
Query Hints AND ADVANCED QUERY
Query hints are the JPA extension point for query features. A hint is simply a string name and object value. Hints allow features to be added to JPA without introducing a new API.
namedQuery.setHint("javax.persistence.query.timeout", 1);
query.setHint("org.hibernate.cacheable", Boolean.TRUE);
Advanced Query: SELECT NEW com.innominds.dto.Employee(e.id,e.name,e.salary,e.joinDate) FROM Employee e
INHERITANCE AND
POLYMORPHISM
SELECT p FROM Project p WHERE p.employees IS
NOT EMPTY
SELECT p FROM Project p WHERE TYPE(p) =
DesignProject OR TYPE(p) = QualityProject
INNER JOIN QUERY EXAMPLE
SELECT pFROM Employee e JOIN e.phones p
SUB QUERIES
SELECT e FROM Employee e WHERE
e.salary = (SELECT MAX(emp.salary) FROM
Employee emp)
COLLECTION EXPRESSION
SELECT e FROM Employee e WHERE
e.directs IS NOT EMPTY
SELECT m FROM Employee m WHERE
(SELECT COUNT(e) FROM Employee e
WHERE e.manager = m) > 0
MEMBER OF The MEMBER OF operator and its negated
form NOT MEMBER OF are a shorthand way
of checking whether an entity is a member of
a collection association path.
SELECT e FROM Employee e WHERE e
MEMBER OF e.directs
Enabling SECOND LEVEL CACHE IN 4.0 (3.3.x) or higher
Hibernate has its own EHCache implementation from version 4 onwards.
Add below properties to configuration
<property name="hibernate.cache.region.factory_class" value="org.hibernate.cache.ehcache.EhCacheRegionFactory"/>
<property name="hibernate.cache.use_second_level_cache" value="true" />
<property name="hibernate.cache.use_query_cache" value="true" />
<property name="hibernate.generate_statistics" value="true" />
Second LEVEL CACHE MODES
Second level cache can be controller using property "javax.persistence.sharedCache.mode".
Following values are allowed
ALL: All entity data is stored in the 2nd level cache
NONE: No data is cached
ENABLE_SELECTIVE: Entities marked with @Cachableare cached
DISABLE_SELECTIVE: All entities except @Cachable(false) are cached
UNSPECIFIED: Caching behavior is not specified, Persistence provider’s default caching behavior is used.
final Properties additionalConfig = new Properties();
additionalConfig.put("javax.persistence.sharedCache.mode", "DISABLE_SELECTIVE");
Cache Retrieval and Store Modes
When the second level cache is enabled for a persistence unit, we’re now able fine-tune the caching behavior by setting retrieval-mode and store-mode-properties at persistence context level or for each entity-manager operation or query level by setting below properties.
Retrieve Mode can be set using below property
javax.persistence.cache.retrieveMode
Store Mode can be set using below property
javax.persistence.cache.storeMode
Retrieve MODES Following options are available for Retrieve mode
BYPASS: The cache is bypassed and a call to the database is used to retrieve the data.
USE: If the data is available in the cache, it is read from this location, else it is fetched from the database.
EX: config.put("javax.persistence.cache.retrieveMode", CacheRetrieveMode.USE);
CACHE STORE MODES
Following options are available for store mode
BYPASS: Don’t put anything into the cache
REFRESH: Data is put/updated in the cache
when read and committed into the database a
refresh enforced
USE: Data is put/updated in the cache when
read and committed into the database
Container Managed EntityManager To demonstrate this scenario I used spring
container to create EntityManagerFactory which reads the configuration from persistence.xml file.
@Bean(name = "entityManagerFactory")
public EntityManagerFactory entityManagerFactory() {
final LocalContainerEntityManagerFactoryBean em = new LocalContainerEntityManagerFactoryBean();
em.afterPropertiesSet();// IMP
return em.getObject();
}
NOTE: full java configuration without using persistence.xmlalso possible please refer the github source code link in the next slide.
Write a Dao class and annotate
EntityManager as shown below
@Repository("personDao")
@Transactional(propagation = Propagation.REQUIRED)
public class PersonDao {
@PersistenceContext
private EntityManager entityManager;
… write your business methods here
}
NOTE: Working code available below location:
https://github.com/Innominds-jee/jpa-cm-training.git
Distributed Transactions using JTA https://www.javacodegeeks.com/2013/07/spring-
jta-multiple-resource-transactions-in-tomcat-with-atomikos-example.html
https://www.atomikos.com/Documentation/HibernateThreeStandalone
http://www.careerride.com/JTS-advantages-of-JTA-over-JTS.aspx
https://spring.io/blog/2011/08/15/configuring-spring-and-jta-without-full-java-ee/
http://www.javaworld.com/article/2077714/java-web-development/xa-transactions-using-spring.html
http://www.byteslounge.com/tutorials/spring-jta-multiple-resource-transactions-in-tomcat-with-atomikos-example