Transcript Document

Enterprise
Java
Java Persistence:
EntityManager
Goals
Enterprise
Java
• Become familiar with the Java Persistence
EntityManager
– API
– Provider
• Hibernate
v070903
Java Persistence: EntityManager
2
Overview
Enterprise
Java
• Earlier versions of EJB Specification defined the
persistence layer
– javax.ejb.EntityBean
• Java EE 5 has moved persistence to its own
specification
– javax.persistence API (1.0)
• ease of use API above JDBC
• Provides
– Object/Relational Mapping (ORM) Engine
– Query Language (SQL-Like, based on former EJB-QL)
v070903
Java Persistence: EntityManager
3
javax.persistence.EntityManager
Enterprise
Java
• Replaces much of the EJB 2.x “Home” functionality
• Handles O/R Mapping of Entities to the database
• Provides APIs
–
–
–
–
inserting objects into database
getting objects from database
synchronizing objects with database
querying database
• Provides caching
• Coordinates with transactional services (JTA)
• Tightly integrated with Java EE and EJB, but not
limited to that environment
v070903
Java Persistence: EntityManager
4
Entities
Enterprise
Java
• (formerly and sometimes still called Entity Beans)
• are now Plain Old Java Objects (POJOs)
– nothing special happens when calling new
Author author = new Author();
• are not persistent until associated with an
EntityManager
em.persist(author);
v070903
Java Persistence: EntityManager
5
Example Author POJO Entity
Enterprise
Java
@javax.persistence.Entity
public class Author {
private long id;
private long version=0;
private String firstName;
private String lastName;
private String subject;
private Date publishDate;
public Author() {}
public Author(long id) { this.id = id; }
...
}
v070903
@Id @GeneratedValue
public long getId() { return id;}
private void setId(long id) {
this.id = id;
}
public String getFirstName() {
return firstName;
}
public void setFirstName(String firstName) {
this.firstName = firstName;
}
Java Persistence: EntityManager
6
Creating Entity in Database
Enterprise
Java
log_.info("testCreate()");
Author author = new Author(); //primary key will be gen
author.setFirstName("dr");
author.setLastName("seuss");
author.setSubject("children");
author.setPublishDate(new Date());
log_.info("creating author:" + author);
em.persist(author);
log_.info("created author:" + author);
//output
-creating author:id=0, fn=dr,
pdate=Fri Sep 15 11:54:15 EDT
-created author:id=50, fn=dr,
pdate=Fri Sep 15 11:54:15 EDT
v070903
ln=seuss, subject=children,
2006
ln=seuss, subject=children,
2006
Java Persistence: EntityManager
7
Managed and Unmanaged Entities
Enterprise
Java
• Unmanaged state (detached)
– instance not associated with an EntityManager
– state changes are not tracked
– can be serialized to client and returned to be
synchronized with database
– nothing equivalent to this state in EJB 2.1 entity beans
• Managed state (attached)
– instance associated with an EntityManager
– state changes are tracked within a Persistence Context
– EJB 2.1 entity beans were always managed
• client interfaced with data through a proxy or state
transferred through a Data Transfer Object
v070903
Java Persistence: EntityManager
8
Persistence Context
Enterprise
Java
• A set of attached entity instances managed by an
EntityManager
• All entities become detached once closed
• Two types
– Transaction-scoped Persistence Contexts
• begin/end at transaction boundaries
• only made available through container managed
persistence contexts
– Extended Persistence Contexts
• live beyond any single transaction
• allow longer-lived interactions with database without
lengthy transactions tying up database resources
v070903
Java Persistence: EntityManager
9
Persistence Context Examples
Enterprise
Java
• Transaction-scoped (inside server container)
@PersistenceContext(unitName=”jpaDemo”)
EntityManager em;
@TransactionAttribute(REQUIRED)
public void update(long authorId, String type) {
Author author = em.find(Author.class, authorId);
author.setType(type);
}
• Extended (inside or outside server container)
EntityManager em = Persistence.
createEntityManagerFactory(“jpaDemo”).createEntityManager();
tx.begin();
//tx 1 begins
Author author = em.find(Author.class, authorId);
tx.commit();
//tx 1 ends, but author remains managed
...
tx.begin();
//tx 2 begins
author.setType(type);
tx.commit();
//tx 2 ends, and author is still managed until close
v070903
Java Persistence: EntityManager
10
Persistence Unit
Enterprise
Java
• A set of classes that are mapped to the database
• defined in META-INF/persistence.xml
• must have an identity
– “” is a valid identity
• Classes
– may be named in persistence.xml file
– may be automatically scanned for in the classpath
• orm.xml
– optionally provided to augment, provide, or replace class
persistence metadata
– (more on orm.xml in Core ORM topic)
v070903
Java Persistence: EntityManager
11
Example Component Layout
Enterprise
Java
META-INF/
+---persistence.xml
ejava
+ ---examples
+---dao
+---DAOException.class
+---AuthorDAO.class
+---jpa
|
+---JPAAuthorDAO.class
|
+---JPADAOBase.class
+--domain
+---Author.class
v070903
Java Persistence: EntityManager
12
Example persistence.xml
Enterprise
Java
<?xml version="1.0" encoding="UTF-8"?>
<persistence xmlns="http://java.sun.com/xml/ns/persistence"
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="jpaDemo">
referenced by name
• global JNDI name by which
provider references resource
(will be used when deployed within server)
• may use properties element in Java SE
environments that lack JNDI
<jta-data-source>java:/ejavaDS</jta-data-source>
<properties>
<property name="hibernate.hbm2ddl.auto" value="create"/>
<property name="jboss.entity.manager.jndi.name"
value="java:/EntityManagers/ejava"/>
</properties>
• vendor-specific way to configure
</persistence-unit>
persistence provider
</persistence>
v070903
Java Persistence: EntityManager
13
Another Example persistence.xml
Enterprise
Java
<?xml version="1.0" encoding="UTF-8"?>
<persistence xmlns="http://java.sun.com/xml/ns/persistence"
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="jpaDemo">
<provider>org.hibernate.ejb.HibernatePersistence</provider>
<properties>
<property name="hibernate.cache.provider_class"
value="net.sf.ehcache.hibernate.Provider"/>
<property name="hibernate.dialect"
value="org.hibernate.dialect.HSQLDialect"/>
<property name="hibernate.connection.url"
value="jdbc:hsqldb:hsql://localhost:9001"/>
<property name="hibernate.connection.driver_class"
value="org.hsqldb.jdbcDriver"/>
<property name="hibernate.connection.password"
value=""/>
<property name="hibernate.connection.username"
value="sa"/>
<property name="hibernate.show_sql" value="false"/>
<property name="hibernate.hbm2ddl.auto" value="create"/>
</properties>
</persistence-unit>
</persistence
v070903
Java Persistence: EntityManager
14
persistence.xml elements
•
•
•
•
•
•
•
•
•
Enterprise
Java
name – identity to reference Persistence Unit
provider – fully qualified name of javax.persistence.PersistenceProvider
– not needed if provider found in classpath acceptable
mapping-file – resource path to optional mapping file
– can be used to specify <class>es or specify/override @Annotation details
jta-data-source
– vendor-specific reference to data source using JTA transactions
non-jta-data-source
– vendor-specific reference to data source using RESOURCE_LOCAL transactions
jar-file
– optional/additional jar file to scan for classes
class
– specifies entity classes not automatically scanned by provider
exclude-unlisted-classes
– if set, provider will not automatically scan archive for entity classes
properties
– may be used to provide vendor-specific properties to configure persistence providers
v070903
Java Persistence: EntityManager
15
Specifying an optional orm.xml file
Enterprise
Java
<?xml version="1.0" encoding="UTF-8"?>
<persistence xmlns="http://java.sun.com/xml/ns/persistence"
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="jpaDemo">
<provider>...</provider>
<mapping-file>META-INF/orm.xml</mapping-file>
<properties>
...
</properties>
</persistence-unit>
</persistence
v070903
Java Persistence: EntityManager
16
Optional orm.xml overrides
Enterprise
Java
<?xml version="1.0" encoding="UTF-8"?>
<entity-mappings xmlns="http://java.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
http://java.sun.com/xml/ns/persistence/orm_1_0.xsd" version="1.0">
<entity class="ejava.examples.dao.domain.Author"
metadata-complete="false">
<table name="DAO_AUTHOR"/>
</entity>
</entity-mappings>
v070903
Java Persistence: EntityManager
17
Entities Discovered
Enterprise
Java
• classes with @Entity annotation
– in the persistence.xml's JAR file
– contained in any JAR file listed in jar-file element
• classes mapped
– with META-INF/orm.xml
– with custom mapping files
• classes listed in persistence.xml's “<class>” element
v070903
Java Persistence: EntityManager
18
Java SE Steps
Enterprise
Java
• Startup
– Get EntityManagerFactory
• Runtime
–
–
–
–
–
Create EntityManager
Start Transaction
Interact with Entity Manager
Commit Transaction
Close EntityManager
• Shutdown
– Close EntityManagerFactory
v070903
Java Persistence: EntityManager
19
javax.persistence.Persistence
Enterprise
Java
• used to bootstrap persistence in Java SE environments
public class javax.persistence.Persistence {
public static java.lang.String PERSISTENCE_PROVIDER;
public javax.persistence.Persistence();
public static EntityManagerFactory
createEntityManagerFactory(String puName);
public static EntityManagerFactory
createEntityManagerFactory(String puName, Map props);
}
• example usage
EntityManagerFactory emf = Persistence
.createEntityManagerFactory(“jpaDemo”);
v070903
Java Persistence: EntityManager
20
Enterprise
Java
javax.persistence.EntityManagerFactory
• used to obtain reference to EntityManager in standard
Java SE environments
package javax.persistence;
public interface EntityManagerFactory{
EntityManager createEntityManager();
EntityManager createEntityManager(Map props);
void close();
boolean isOpen();
}
• Map used to supply or override properties in
persistence.xml
• close() and isOpen() only valid for non-injected EMFs
• example usage
– EntityManager em = emf.createEntityManagerFactory();
v070903
Java Persistence: EntityManager
21
javax.persistence.EntityManager
Enterprise
Java
package javax.persistence;
public interface EntityManager{
EntityTransaction getTransaction();
void persist(java.lang.Object);
Object<T> find(Class<T>, Object pKey);
Object<T> getReference(Class<T>, Object pKey);
boolean contains(Object);
Object merge(java.lang.Object);
void refresh(java.lang.Object);
void remove(java.lang.Object);
Object find(java.lang.Class, java.lang.Object);
void flush();
void clear();
void close();
isOpen();
--Query
Query
Query
Query
Query
v070903
...
createQuery(java.lang.String);
createNamedQuery(java.lang.String);
createNativeQuery(java.lang.String);
createNativeQuery(java.lang.String, java.lang.Class);
createNativeQuery(java.lang.String, java.lang.String);
Java Persistence: EntityManager
22
persist()
Enterprise
Java
Author author = new Author(nextId());
author.setFirstName("dr");
author.setLastName("seuss");
author.setSubject("children");
author.setPublishDate(new Date());
em.persist(author);
• Extended persistence contexts
– queues write until associated with transaction
• Transaction-scoped persistence contexts
– illegal to call outside the scope of a transaction
• Actual write to the database depends on FlushMode
– manually controlled with flush() call
v070903
Java Persistence: EntityManager
23
find()
Enterprise
Java
Author author2=null;
author2 = em.find(Author.class, id);
log_.info("got author author:" + author2);
got author author:id=51, fn=thing, ln=one, subject=children,
pdate=Fri Sep 15 11:54:15 EDT 2006
• Returns an instance of the class associated with the specified primary
key value
– relationships are instantiated according to lazy-loading policies
• Returns null if primary key not found
• Uses generics, so no casting is necessary
• Ids can be autoboxed without a manual wrapper
• can be called outside the scope of a transaction
• will be attached to open persistence context
– second find() will return same object
v070903
Java Persistence: EntityManager
24
getReference()
Enterprise
Java
Author author2=null;
author2 = em.getReference(Author.class, id);
log_.info("got author author:" + author2);
• Similar to find()
– Returns an instance of the class associated with the
specified primary key value
• no guarantee that object state initialized
– Throws EntityNotFoundException if primary key not
found
v070903
Java Persistence: EntityManager
25
createQuery()
Enterprise
Java
• 5 createQuery() methods
Query
Query
Query
Query
Query
createQuery(String ejbqlString);
createNamedQuery(String name);
createNativeQuery(String sqlString);
createNativeQuery(String sqlString, Class resultClass);
createNativeQuery(String sqlString, String resultSetMap);
• example usage
Query query = em.createQuery("from jpaAuthor where id=" + id);
Author author = (Author)query.getSingleResult();
• use EJB-QL and native (SQL) query languages
• similar to find/getReference()
–returned objects attached to open persistence context
v070903
Java Persistence: EntityManager
26
updating entities
Enterprise
Java
• Updates to managed entities automatically get
propagated to database according to flush policy
public Author update(Author author) {
Author dbAuthor = em.find(Author.class,author.getId());
dbAuthor.setFirstName(author.getFirstName());
dbAuthor.setLastName(author.getLastName());
dbAuthor.setSubject(author.getSubject());
dbAuthor.setPublishDate(author.getPublishDate());
return dbAuthor;
}
v070903
Java Persistence: EntityManager
27
merge()
Enterprise
Java
• merges state changes to detached objects back into
persistent storage
public Author updateByMerge(Author author) {
Author managedAuthor = em.merge(author);
return managedAuthor;
}
• Original is left detached
• Object returned is managed
• Returned object is added to persistence if did not
already exist
• Updates are made to existing object if already exists
v070903
Java Persistence: EntityManager
28
remove()
Enterprise
Java
public void remove(Author author) {
em.remove(author);
}
– removes object from database
• physically performed in database according to flush policy
• cascades to related objects according to cascade policy
– object will be detached
v070903
Java Persistence: EntityManager
29
refresh() and contains()
Enterprise
Java
• refresh()
Author author = em.find(Author.class, id);
em.refresh(author);
– used to make sure entity is in sync with database
• cascades to related entities depending on cascade policy
– entity must be currently managed by entity manager
instance
• contains()
if (em.contains(author)) {
...
}
– used to test if instance is being managed by entity
manager instance
v070903
Java Persistence: EntityManager
30
clear() and flush()
•
•
Enterprise
Java
clear()
– detaches all entities
– does not commit queued changes
• call flush() prior to clear()
flush()
– changes not synchronized with database until entity manager flushed
• persist(), merge(), remove()
– occurs automatically before executing
• correlated queries
– permits query to reflect changes in persistence context
• transaction commit
– not impacted by primary key finders
• find(), getReference()
– FlushMode
• AUTO – default and most sane
• COMMIT – an optimization to only flush and end of transaction. May
limit amount of database locking that occurs
v070903
Java Persistence: EntityManager
31
lock() and getDelegate()
Enterprise
Java
• lock()
– provides a pessimistic write lock for entity
– will be covered with later during transaction topics
• getDelegate()
– returns vendor object that implements EntityManager
interface
– used to expose vendor-specific extension API
v070903
Java Persistence: EntityManager
32
EntityTransactions
Enterprise
Java
• Only available for Entity Managers with an extended
persistence context
– Transaction-scoped persistence contexts are only
available with containers that support JTA transactions
– Extended persistence contexts generally pertain to Java
SE applications using javax.persistence.Persistence class
to get EntityManagerFactory
• transaction-like API for managing transactions within
the single resource
• transaction context obtained from EntityManager
javax.persistence.EntityTransaction tx =
em.getTransaction();
tx.begin()
tx.commit()
tx.isActive()
tx.rollback()
v070903
Java Persistence: EntityManager
33
Example
Enterprise
Java
private EntityManager em = ...
public void testQuery() throws Exception {
Author author = new Author();
author.setFirstName("test");
author.setLastName("Query");
author.setSubject("testing");
author.setPublishDate(new Date());
em.persist(author);
//need to associate em with Tx to allow query to see entity in DB
try {
em.getTransaction().begin();
//note that the persist does not have to be within the tx
em.getTransaction().commit();
}
catch (Exception ex) {
em.getTransaction().rollback();
fail("" + ex);
}
Author author2 = null;
Query query = em.createQuery(
"from jpaAuthor where id=" + author.getId());
author2 = (Author)query.getSingleResult();
}
v070903
assertNotNull(author2);
assertEquals(author.getFirstName(), author2.getFirstName());
assertEquals(author.getLastName(), author2.getLastName());
assertEquals(author.getSubject(), author2.getSubject());
assertEquals(author.getPublishDate(), author2.getPublishDate());
Java Persistence: EntityManager
34
Enterprise
Java
Hibernate Persistence Container
v070903
Java Persistence: EntityManager
35
Classpath
•
•
•
•
Enterprise
Java
hibernate.jar
hibernate-annotations.jar
hibernate-entitymanager.jat
third party jars
– automatically downloaded with maven
– can also get them using the thirdparty-all.jar that is
distributed with the JBoss embeddable container
v070903
Java Persistence: EntityManager
36
Enterprise
Java
Example Hibernate Maven Dependencies
<dependency>
<groupId>org.hibernate</groupId>
<artifactId>hibernate</artifactId>
<version>3.2.1.ga</version>
<scope>test</scope>
</dependency>
<dependency>
<groupId>org.hibernate</groupId>
<artifactId>hibernate-annotations</artifactId>
<version>3.2.1.ga</version>
<scope>test</scope>
</dependency>
<dependency>
<groupId>org.hibernate</groupId>
<artifactId>hibernate-entitymanager</artifactId>
<version>3.2.1.ga</version>
<scope>test</scope>
</dependency>
v070903
Java Persistence: EntityManager
37
JPAUtil.java
Enterprise
Java
package ejava.examples.dao.jpa;
import
import
import
import
java.util.HashMap;
java.util.Map;
javax.persistence.EntityManagerFactory;
javax.persistence.Persistence;
public class JPAUtil {
private static final Map<String, EntityManagerFactory> factories =
new HashMap<String, EntityManagerFactory>();
public static EntityManagerFactory getEntityManagerFactory(String puName) {
EntityManagerFactory emf = factories.get(puName);
if (emf == null) {
synchronized(factories) {
emf = factories.get(puName);
if (emf == null) {
emf = Persistence.createEntityManagerFactory(puName);
factories.put(puName, emf);
}
}
}
return emf;
}
public static void close() {
synchronized(factories) {
for(String puName : factories.keySet()) {
factories.get(puName).close();
}
factories.clear();
}
}
}
v070903
Java Persistence: EntityManager
38
JUnit Setup
Enterprise
Java
public class AllTest extends TestCase {
private static Log log_ = LogFactory.getLog(AllTest.class);
public static Test suite() {
TestSuite tests = new TestSuite();
tests.addTestSuite(JPAExtendedOnlyDemo.class);
TestSetup wrapper = new TestSetup(tests) {
//one-time setup
public void setUp() throws Exception {
}
//one-time tear down
public void tearDown() throws Exception {
JPAUtil.close();
}
};
}
v070903
return wrapper;
Java Persistence: EntityManager
39
JUnit Tests
Enterprise
Java
public class JPAExtendedOnlyDemo extends TestCase {
private EntityManager em;
public void setUp() throws Exception {
EntityManagerFactory emf =
JPAUtil.getEntityManagerFactory(“jpaDemo”);
em = emf.createEntityManager();
}
public void tearDown() throws Exception {
em.getTransaction().begin();
em.flush();
em.close();
em.getTransaction().commit();
}
public void testCreate() throws Exception {
Author author = new Author();
author.setFirstName("dr");
author.setLastName("seuss");
author.setSubject("children");
author.setPublishDate(new Date());
}
v070903
em.persist(author);
Java Persistence: EntityManager
40
Build and Test Environment
Enterprise
Java
<build>
<plugins>
<!-- make sure we are building java5 -->
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-compiler-plugin</artifactId>
<configuration>
<source>1.5</source>
<target>1.5</target>
</configuration>
</plugin>
<!-- set test JVM root classpath so persistence framework
can locate entities during classpath scan -->
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-surefire-plugin</artifactId>
<configuration>
<argLine>${surefire.argLine}</argLine>
<systemProperties>
<property>
<name>java.class.path</name>
<value>target/classes</value>
</property>
</systemProperties>
</configuration>
</plugin>
v070903
Java Persistence: EntityManager
41
Summary
•
•
•
•
•
•
•
Enterprise
Java
Java Persistence API
– Java standard for mapping objects to relational databases
– currently part of Java EE; will be in Java SE 6
– eliminates the need or desire for EJB 2.1 entity
Entity
– a POJO
– operates both detached and managed by OR Mapping
Persistence Unit
– a set of entity classes mapped to the database schema
Persistence Context
– a set of objects that managed
– Transaction-scoped or Extended
javax.persistence.EntityManager
– manages objects in a persistence context
javax.persistence.EntityManagerFactory
– used to create individual entity managers
javax.persistence.Persistence
– used to bootstrap EntityManagerFactory into Java SE applications
v070903
Java Persistence: EntityManager
42
References
Enterprise
Java
• “Enterprise JavaBeans 3.0, 5th Edition”; Burke &
Monsen-Haefel; ISBN 0-596-00978-X; O'Reilly
v070903
Java Persistence: EntityManager
43