Application-Managed Entity Managers | Container-Managed Entity Managers |
Specified by using the entity manager factory to obtain an entity manager instance | Specified by using @PersistenceContext annotation or
JNDI
lookup to obtain an entity manager instance |
Must use extended-scope persistence context | Must use transaction-scoped persistence context |
Must use application-managed transactions | Must use application-managed transactions |
@PersistenceUnit(unitName="CatalogPu") EntityManagerFactory emf
.
Then
the code should hold it for re-use until done using its entity
managers. The EntityManagerFactory is threadsafe so can be kept at
application scope, so it is recommended that web-only applications
using application-managed entity managers
cache it at application scope and share it among requests. Note that if
an application closes an entity manager factory
then all its entity managers are considered in the closed state. EntityManager em = emf.createEntityManager()
.
The entity manager APIs can then be used to persist or query entities. @PersistenceUnit
private
EntityManagerFactory emf;//declared as instance variable for re-use.
...
//this method uses entity manager to persist an entity Item.java
public void addItem(Item item){
EntityManager em = emf.createEntityManager();
try{
...
em.persist(item);
...
} finally {
em.close();
}
close
,
isOpen
, and joinTransaction
to
manage entity managers and their
lifecycle. The application
needs to close the entity manager when finished using it. The
EntityManager is not thread-safe so you should not
hold references to instances of an EntityManager in a manner that is
not threadsafe. Since application-managed entity managers have
extended-scoped persistence contexts, the code can choose to leave the
entity manager open for several requests and close it when done.
Application-managed entity managers can also mimic the behavior of
transaction-scoped entity managers and close the entity manager at the
end of the same method
that created it. In this way, extended-scoped persistence contexts
offer more flexibililty as they can achieve the behavior of
transaction-scoped persistence contexts as well as span multiple HTTP
requests and multiple transactions. One use case for leaving an entity
manager open and using extended-scoped persistence contexts is for
multi-page forms which might use several form submits to gather all the
user information in the entities, then once it has all gathered all the
entities can be flushed and committed to the database. javax.persistence.EntityManager
interface
require that they must be invoked within a transaction context. These
methods throw a TransactionRequiredException
if there is
no transaction and the persistence context is transaction-scoped. These
methods do writes or updates to the data in the database. The developer
should make sure there exists a transaction context
before calling these methods. These methods are the persist
,
merge
, remove
, flush
,
and refresh
methods.Code for JTA entity managers | Code for resource-local entity manager |
@PersistenceUnit EntityManagerFactory emf; |
@PersistenceUnit
private
EntityManagerFactory emf; ... |
Bad Practice: Not Threadsafe, so a bad idea |
Good Practice: Threadsafe. Declares JNDI dependency at top with annotation. Using JNDI Lookup to get entity manager. |
public class MyServlet extends HttpServelet {
@PersistenceContext
EntityManager em; public void doGet( HttpServletRequest req,
... the same
//entity manager instance em.persist(item) ....some code
using the entity manager } |
entity manager so this method-scoped em is thread safe. also notice JNDI lookup to get em ....some code
using the entity manager } |
@PersistenceContext(name="foo",
unitName="myPuName")
public class MyServlet extends HttpServelet {
@Resource UserTransaction utx;
public void doGet(HttpServletRequest req,
HttpServletResponse resp) throws throws
ServletException, IOException {
EntityManager em = (EntityManager) ic.lookup("java:comp/env/foo");
//get data from request
String name = request.getParameter("item_name");
...
//create new Item entity
Item item = new Item();
//set values of Item entity
item.setName(name);
...
utx.begin();
em.persist(item); //persist and add new Item to database
utx.commit();
...
}
@Resource
annotation
injects a UserTransaction instance that
is used
to control JTA transactions. UserTransaction is threadsafe so can be
held as an instance variable that is shared by other requests. Since we
are doing a database write here,
we start a transaction just before calling em.persist()
and commit it afterwards.
The container manages the lifecycle of the entity manager instance and
closes it at the end of the method. Notice that Servlet class has an
annotation @PersistenceContext(name="foo",
unitName="myPuName")
which
is used to declare a dependency on the persistence context, and then in
the Servlet.doGet method uses JNDI to lookup and get an entity manager
with EntityManager em = ic.lookup("java:comp/env/foo")
.