openjpa-project/src/doc/manual/jpa_overview_em.xml (1,122 lines of code) (raw):

<?xml version="1.0" encoding="UTF-8"?> <!-- Licensed to the Apache Software Foundation (ASF) under one or more contributor license agreements. See the NOTICE file distributed with this work for additional information regarding copyright ownership. The ASF licenses this file to you under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with the License. You may obtain a copy of the License at http://www.apache.org/licenses/LICENSE-2.0 Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the specific language governing permissions and limitations under the License. --> <chapter id="jpa_overview_em"> <title> EntityManager </title> <indexterm zone="jpa_overview_em"> <primary> EntityManager </primary> </indexterm> <mediaobject> <imageobject> <!-- PNG image data, 283 x 391 (see README) --> <imagedata fileref="img/entitymanager.png" width="189px"/> </imageobject> </mediaobject> <para> The diagram above presents an overview of the <classname>EntityManager </classname> interface. For a complete treatment of the <classname> EntityManager</classname> API, see the <ulink url="http://download.oracle.com/javaee/6/api/javax/persistence/EntityManager.html"> Javadoc</ulink> documentation. Methods whose parameter signatures consist of an ellipsis (...) are overloaded to take multiple parameter types. </para> <note> <para> OpenJPA extends the standard <classname>EntityManager</classname> interface with the <ulink url="../../apidocs/org/apache/openjpa/persistence/OpenJPAEntityManager.html"> <classname>org.apache.openjpa.persistence.OpenJPAEntityManager</classname> </ulink> interface to provide additional functionality. </para> </note> <para> The <classname>EntityManager</classname> is the primary interface used by application developers to interact with the JPA runtime. The methods of the <classname>EntityManager</classname> can be divided into the following functional categories: </para> <itemizedlist> <listitem> <para> <classname>Transaction</classname> association. </para> </listitem> <listitem> <para> Entity lifecycle management. </para> </listitem> <listitem> <para> Entity identity management. </para> </listitem> <listitem> <para> Cache management. </para> </listitem> <listitem> <para> <classname>Query</classname> factory. </para> </listitem> <listitem> <para> Entity locking. </para> </listitem> <listitem> <para> Closing. </para> </listitem> </itemizedlist> <section id="jpa_overview_em_trans"> <title> Transaction Association </title> <indexterm zone="jpa_overview_em_trans"> <primary> EntityManager </primary> <secondary> obtaining the Transaction </secondary> <seealso> transactions </seealso> </indexterm> <indexterm zone="jpa_overview_em_trans"> <primary> Transaction </primary> <secondary> obtaining from EntityManager </secondary> </indexterm> <programlisting> public EntityTransaction getTransaction(); </programlisting> <para> Every <classname>EntityManager</classname> has a one-to-one relation with an <link linkend="jpa_overview_trans"><classname>EntityTransaction</classname> </link> instance. In fact, many vendors use a single class to implement both the <classname>EntityManager</classname> and <classname>EntityTransaction </classname> interfaces. If your application requires multiple concurrent transactions, you will use multiple <classname>EntityManager</classname>s. </para> <para> You can retrieve the <classname>EntityTransaction</classname> associated with an <classname>EntityManager</classname> through the <methodname>getTransaction </methodname> method. Note that most JPA implementations can integrate with an application server's managed transactions. If you take advantage of this feature, you will control transactions by declarative demarcation or through the Java Transaction API (JTA) rather than through the <classname>EntityTransaction</classname>. </para> </section> <section id="jpa_overview_em_lifecycle"> <title> Entity Lifecycle Management </title> <indexterm zone="jpa_overview_em_lifecycle"> <primary> EntityManager </primary> <secondary> lifecycle operations </secondary> </indexterm> <para> <classname>EntityManager</classname>s perform several actions that affect the lifecycle state of entity instances. </para> <programlisting> public void persist(Object entity); </programlisting> <para> <indexterm> <primary> EntityManager </primary> <secondary> persist </secondary> </indexterm> <indexterm> <primary> persist </primary> <seealso> EntityManager </seealso> </indexterm> <indexterm> <primary> persistent objects </primary> <secondary> persisting </secondary> </indexterm> Transitions new instances to managed. On the next flush or commit, the newly persisted instances will be inserted into the datastore. </para> <para> For a given entity <literal>A</literal>, the <methodname>persist</methodname> method behaves as follows: </para> <itemizedlist> <listitem> <para> If <literal>A</literal> is a new entity, it becomes managed. </para> </listitem> <listitem> <para> If <literal>A</literal> is an existing managed entity, it is ignored. However, the persist operation cascades as defined below. </para> </listitem> <listitem> <para> If <literal>A</literal> is a removed entity, it becomes managed. </para> </listitem> <listitem> <para> If <literal>A</literal> is a detached entity, an <classname> IllegalArgumentException</classname> is thrown. </para> </listitem> <listitem> <para> The persist operation recurses on all relation fields of <literal>A</literal> whose <link linkend="jpa_overview_meta_cascade">cascades</link> include <literal>CascadeType.PERSIST</literal>. </para> </listitem> </itemizedlist> <para> This action can only be used in the context of an active transaction. </para> <programlisting> public void remove(Object entity); </programlisting> <para> <indexterm> <primary> EntityManager </primary> <secondary> remove </secondary> </indexterm> <indexterm> <primary> remove </primary> <seealso> EntityManager </seealso> </indexterm> <indexterm> <primary> persistent objects </primary> <secondary> deleting </secondary> </indexterm> Transitions managed instances to removed. The instances will be deleted from the datastore on the next flush or commit. Accessing a removed entity has undefined results. </para> <para> For a given entity <literal>A</literal>, the <methodname>remove</methodname> method behaves as follows: </para> <itemizedlist> <listitem> <para> If <literal>A</literal> is a new entity, it is ignored. However, the remove operation cascades as defined below. </para> </listitem> <listitem> <para> If <literal>A</literal> is an existing managed entity, it becomes removed. </para> </listitem> <listitem> <para> If <literal>A</literal> is a removed entity, it is ignored. </para> </listitem> <listitem> <para> If <literal>A</literal> is a detached entity, an <classname> IllegalArgumentException</classname> is thrown. </para> </listitem> <listitem> <para> The remove operation recurses on all relation fields of <literal>A</literal> whose <link linkend="jpa_overview_meta_cascade">cascades</link> include <literal>CascadeType.REMOVE</literal>. </para> </listitem> </itemizedlist> <para> This action can only be used in the context of an active transaction. </para> <programlisting> public void refresh(Object entity); </programlisting> <para> <indexterm> <primary> EntityManager </primary> <secondary> refresh </secondary> </indexterm> <indexterm> <primary> refresh </primary> <seealso> EntityManager </seealso> </indexterm> <indexterm> <primary> persistent objects </primary> <secondary> refreshing state </secondary> </indexterm> <indexterm> <primary> transactions </primary> <secondary> optimistic </secondary> </indexterm> Use the <methodname>refresh</methodname> action to make sure the persistent state of an instance is synchronized with the values in the datastore. <methodname>refresh</methodname> is intended for long-running optimistic transactions in which there is a danger of seeing stale data. </para> <para> For a given entity <literal>A</literal>, the <methodname>refresh</methodname> method behaves as follows: </para> <itemizedlist> <listitem> <para> If <literal>A</literal> is a new entity, it is ignored. However, the refresh operation cascades as defined below. </para> </listitem> <listitem> <para> If <literal>A</literal> is an existing managed entity, its state is refreshed from the datastore. </para> </listitem> <listitem> <para> If <literal>A</literal> is a removed entity, it is ignored. </para> </listitem> <listitem> <para> If <literal>A</literal> is a detached entity, an <classname> IllegalArgumentException</classname> is thrown. </para> </listitem> <listitem> <para> The refresh operation recurses on all relation fields of <literal>A</literal> whose <link linkend="jpa_overview_meta_cascade">cascades</link> include <literal>CascadeType.REFRESH</literal>. </para> </listitem> </itemizedlist> <programlisting> public Object merge(Object entity); </programlisting> <para> <indexterm> <primary> EntityManager </primary> <secondary> merge </secondary> <seealso> detachment </seealso> </indexterm> <indexterm> <primary> detachment </primary> <secondary> JPA </secondary> </indexterm> <indexterm> <primary> merge </primary> <seealso> detachment </seealso> </indexterm> <indexterm> <primary> data transfer object </primary> </indexterm> <indexterm> <primary> value object </primary> </indexterm> A common use case for an application running in a servlet or application server is to "detach" objects from all server resources, modify them, and then "attach" them again. For example, a servlet might store persistent data in a user session between a modification based on a series of web forms. Between each form request, the web container might decide to serialize the session, requiring that the stored persistent state be disassociated from any other resources. Similarly, a client/server application might transfer persistent objects to a client via serialization, allow the client to modify their state, and then have the client return the modified data in order to be saved. This is sometimes referred to as the <emphasis>data transfer object</emphasis> or <emphasis>value object</emphasis> pattern, and it allows fine-grained manipulation of data objects without incurring the overhead of multiple remote method invocations. </para> <para> JPA provides support for this pattern by automatically detaching entities when they are serialized or when a persistence context ends (see <xref linkend="jpa_overview_emfactory_perscontext"/> for an exploration of persistence contexts). The JPA <emphasis>merge</emphasis> API re-attaches detached entities. This allows you to detach a persistent instance, modify the detached instance offline, and merge the instance back into an <classname>EntityManager</classname> (either the same one that detached the instance, or a new one). The changes will then be applied to the existing instance from the datastore. </para> <para> A detached entity maintains its persistent identity, but cannot load additional state from the datastore. Accessing any persistent field or property that was not loaded at the time of detachment has undefined results. Also, be sure not to alter the version or identity fields of detached instances if you plan on merging them later. </para> <para> The <methodname>merge</methodname> method returns a managed copy of the given detached entity. Changes made to the persistent state of the detached entity are applied to this managed instance. Because merging involves changing persistent state, you can only merge within a transaction. </para> <para> If you attempt to merge an instance whose representation has changed in the datastore since detachment, the merge operation will throw an exception, or the transaction in which you perform the merge will fail on commit, just as if a normal optimistic conflict were detected. </para> <note> <para> OpenJPA offers enhancements to JPA detachment functionality, including additional options to control which fields are detached. See <xref linkend="ref_guide_detach"/> in the Reference Guide for details. </para> </note> <para> For a given entity <literal>A</literal>, the <methodname>merge</methodname> method behaves as follows: </para> <itemizedlist> <listitem> <para> If <literal>A</literal> is a detached entity, its state is copied into existing managed instance <literal>A'</literal> of the same entity identity, or a new managed copy of <literal>A</literal> is created. </para> </listitem> <listitem> <para> If <literal>A</literal> is a new entity, a new managed entity <literal>A' </literal> is created and the state of <literal>A</literal> is copied into <literal>A'</literal>. </para> </listitem> <listitem> <para> If <literal>A</literal> is an existing managed entity, it is ignored. However, the merge operation still cascades as defined below. </para> </listitem> <listitem> <para> If <literal>A</literal> is a removed entity, an <classname> IllegalArgumentException</classname> is thrown. </para> </listitem> <listitem> <para> The merge operation recurses on all relation fields of <literal>A</literal> whose <link linkend="jpa_overview_meta_cascade">cascades</link> include <literal>CascadeType.MERGE</literal>. </para> </listitem> </itemizedlist> <para> The following diagram illustrates the lifecycle of an entity with respect to the APIs presented in this section. </para> <mediaobject> <imageobject> <!-- PNG image data, 445 x 337 (see README) --> <imagedata fileref="img/jpa-state-transitions.png" width="297px"/> </imageobject> </mediaobject> </section> <section id="jpa_overview_em_lifeexamples"> <title> Lifecycle Examples </title> <para> The examples below demonstrate how to use the lifecycle methods presented in the previous section. The examples are appropriate for out-of-container use. Within a container, <classname> EntityManager</classname>s are usually injected, and transactions are usually managed. You would therefore omit the <methodname> createEntityManager</methodname> and <methodname>close</methodname> calls, as well as all transaction demarcation code. </para> <example id="jpa_overview_em_lifecycle_persist"> <title> Persisting Objects </title> <indexterm> <primary> persistent objects </primary> <secondary> persisting </secondary> <tertiary> example </tertiary> </indexterm> <programlisting> // create some objects Magazine mag = new Magazine("1B78-YU9L", "JavaWorld"); Company pub = new Company("Weston House"); pub.setRevenue(1750000D); mag.setPublisher(pub); pub.addMagazine(mag); Article art = new Article("JPA Rules!", "Transparent Object Persistence"); art.addAuthor(new Author("Fred", "Hoyle")); mag.addArticle(art); // persist EntityManager em = emf.createEntityManager(); em.getTransaction().begin(); em.persist(mag); em.persist(pub); em.persist(art); em.getTransaction().commit(); // or we could continue using the EntityManager... em.close(); </programlisting> </example> <example id="jpa_overview_em_lifecycle_update"> <title> Updating Objects </title> <indexterm> <primary> persistent objects </primary> <secondary> updating </secondary> <tertiary> example </tertiary> </indexterm> <programlisting> Magazine.MagazineId mi = new Magazine.MagazineId(); mi.isbn = "1B78-YU9L"; mi.title = "JavaWorld"; // updates should always be made within transactions; note that // there is no code explicitly linking the magazine or company // with the transaction; JPA automatically tracks all changes EntityManager em = emf.createEntityManager(); em.getTransaction().begin(); Magazine mag = em.find(Magazine.class, mi); mag.setPrice(5.99); Company pub = mag.getPublisher(); pub.setRevenue(1750000D); em.getTransaction().commit(); // or we could continue using the EntityManager... em.close(); </programlisting> </example> <example id="jpa_overview_em_lifecycle_delete"> <title> Removing Objects </title> <indexterm> <primary> persistent objects </primary> <secondary> deleting </secondary> <tertiary> example </tertiary> </indexterm> <programlisting> // assume we have an object id for the company whose subscriptions // we want to delete Object oid = ...; // deletes should always be made within transactions EntityManager em = emf.createEntityManager(); em.getTransaction().begin(); Company pub = (Company) em.find(Company.class, oid); for (Subscription sub : pub.getSubscriptions()) em.remove(sub); pub.getSubscriptions().clear(); em.getTransaction().commit(); // or we could continue using the EntityManager... em.close(); </programlisting> </example> <example id="jpa_overview_em_detachex"> <title> Detaching and Merging </title> <para> This example demonstrates a common client/server scenario. The client requests objects and makes changes to them, while the server handles the object lookups and transactions. </para> <programlisting> // CLIENT: // requests an object with a given oid Record detached = (Record) getFromServer(oid); ... // SERVER: // send object to client; object detaches on EM close Object oid = processClientRequest(); EntityManager em = emf.createEntityManager(); Record record = em.find(Record.class, oid); em.close(); sendToClient(record); ... // CLIENT: // makes some modifications and sends back to server detached.setSomeField("bar"); sendToServer(detached); ... // SERVER: // merges the instance and commit the changes Record modified = (Record) processClientRequest(); EntityManager em = emf.createEntityManager(); em.getTransaction().begin(); Record merged = (Record) em.merge(modified); merged.setLastModified(System.currentTimeMillis()); merged.setModifier(getClientIdentityCode()); em.getTransaction().commit(); em.close(); </programlisting> </example> </section> <section id="jpa_overview_em_identity"> <title> Entity Identity Management </title> <para> Each <classname>EntityManager</classname> is responsible for managing the persistent identities of the managed objects in the persistence context. The following methods allow you to interact with the management of persistent identities. The behavior of these methods is deeply affected by the persistence context type of the <classname>EntityManager</classname>; see <xref linkend="jpa_overview_emfactory_perscontext"/> for an explanation of persistence contexts. </para> <programlisting> public &lt;T&gt; T find(Class&lt;T&gt; cls, Object oid); </programlisting> <para> <indexterm> <primary> EntityManager </primary> <secondary> find </secondary> <seealso> identity </seealso> </indexterm> <indexterm> <primary> find </primary> <seealso> EntityManager </seealso> </indexterm> <indexterm> <primary> identity </primary> <secondary> retrieving objects by identity </secondary> </indexterm> This method returns the persistent instance of the given type with the given persistent identity. If the instance is already present in the current persistence context, the cached version will be returned. Otherwise, a new instance will be constructed and loaded with state from the datastore. If no entity with the given type and identity exists in the datastore, this method returns null. </para> <programlisting> public &lt;T&gt; T getReference(Class&lt;T&gt; cls, Object oid); </programlisting> <para> <indexterm> <primary> EntityManager </primary> <secondary> getReference </secondary> <seealso> identity </seealso> </indexterm> <indexterm> <primary> getReference </primary> <seealso> EntityManager </seealso> </indexterm> <indexterm> <primary> identity </primary> <secondary> retrieving objects by identity </secondary> </indexterm> <indexterm> <primary> EntityNotFoundException </primary> </indexterm> This method is similar to <methodname>find</methodname>, but does not necessarily go to the database when the entity is not found in cache. The implementation may construct a <emphasis>hollow</emphasis> entity and return it to you instead. Hollow entities do not have any state loaded. The state only gets loaded when you attempt to access a persistent field. At that time, the implementation may throw an <classname>EntityNotFoundException</classname> if it discovers that the entity does not exist in the datastore. The implementation may also throw an <classname>EntityNotFoundException</classname> from the <methodname>getReference</methodname> method itself. Unlike <methodname> find</methodname>, <methodname>getReference</methodname> does not return null. </para> <programlisting> public boolean contains(Object entity); </programlisting> <para> <indexterm> <primary> EntityManager </primary> <secondary> contains </secondary> </indexterm> <indexterm> <primary> contains </primary> <seealso> EntityManager </seealso> </indexterm> Returns true if the given entity is part of the current persistence context, and false otherwise. Removed entities are not considered part of the current persistence context. </para> </section> <section id="jpa_overview_em_cache"> <title> Cache Management </title> <indexterm zone="jpa_overview_em_cache"> <primary> EntityManager </primary> <secondary> cache </secondary> </indexterm> <programlisting> public void flush(); </programlisting> <para> <indexterm> <primary> EntityManager </primary> <secondary> flush </secondary> </indexterm> <indexterm> <primary> flush </primary> <seealso> EntityManager </seealso> </indexterm> <indexterm> <primary> transactions </primary> <secondary> flushing changes before commit </secondary> </indexterm> The <methodname>flush</methodname> method writes any changes that have been made in the current transaction to the datastore. If the <classname>EntityManager </classname> does not already have a connection to the datastore, it obtains one for the flush and retains it for the duration of the transaction. Any exceptions during flush cause the transaction to be marked for rollback. See <xref linkend="jpa_overview_trans"/>. </para> <para> Flushing requires an active transaction. If there isn't a transaction in progress, the <methodname>flush</methodname> method throws a <classname> TransactionRequiredException</classname>. </para> <programlisting> public FlushModeType getFlushMode(); public void setFlushMode(FlushModeType flushMode); </programlisting> <para> <indexterm> <primary> EntityManager </primary> <secondary> FlushMode </secondary> </indexterm> <indexterm> <primary> FlushMode </primary> </indexterm> The <classname>EntityManager</classname>'s <literal>FlushMode</literal> property controls whether to flush transactional changes before executing queries. This allows the query results to take into account changes you have made during the current transaction. Available <ulink url="http://download.oracle.com/javaee/6/api/javax/persistence/FlushModeType.html"> <classname>jakarta.persistence.FlushModeType</classname></ulink> constants are: </para> <itemizedlist> <listitem> <para> <literal>COMMIT</literal>: Only flush when committing, or when told to do so through the <methodname>flush</methodname> method. Query results may not take into account changes made in the current transaction. </para> </listitem> <listitem> <para> <literal>AUTO</literal>: The implementation is permitted to flush before queries to ensure that the results reflect the most recent object state. </para> </listitem> </itemizedlist> <para> You can also set the flush mode on individual <link linkend="jpa_overview_query"><classname>Query</classname></link> instances. </para> <note> <para> OpenJPA only flushes before a query if the query might be affected by data changed in the current transaction. Additionally, OpenJPA allows fine-grained control over flushing behavior. See the Reference Guide's <xref linkend="ref_guide_dbsetup_retain"/>. </para> </note> <programlisting> public void clear(); </programlisting> <para> <indexterm> <primary> EntityManager </primary> <secondary> clear </secondary> </indexterm> <indexterm> <primary> clear </primary> <seealso> EntityManager </seealso> </indexterm> Clearing the <classname>EntityManager</classname> effectively ends the persistence context. All entities managed by the <classname>EntityManager </classname> become detached. </para> </section> <section id="jpa_overview_em_query"> <title> Query Factory </title> <indexterm zone="jpa_overview_em_query"> <primary> EntityManager </primary> <secondary> as Query factory </secondary> <seealso> Query </seealso> </indexterm> <indexterm zone="jpa_overview_em_query"> <primary> Query </primary> <secondary> creating </secondary> </indexterm> <programlisting> public Query createQuery(String query); </programlisting> <para> <classname>Query</classname> objects are used to find entities matching certain criteria. The <methodname>createQuery</methodname> method creates a query using the given Java Persistence Query Language (JPQL) string. See <xref linkend="jpa_overview_query"/> for details. </para> <programlisting> public Query createNamedQuery(String name); </programlisting> <para> This method retrieves a query defined in metadata by name. The returned <classname>Query</classname> instance is initialized with the information declared in metadata. For more information on named queries, read <xref linkend="jpa_overview_query_named"/>. </para> <programlisting> public Query createNativeQuery(String sql); public Query createNativeQuery(String sql, Class resultCls); public Query createNativeQuery(String sql, String resultMapping); </programlisting> <para> <emphasis>Native</emphasis> queries are queries in the datastore's native language. For relational databases, this is the Structured Query Language (SQL). <xref linkend="jpa_overview_sqlquery"/> elaborates on JPA's native query support. </para> </section> <section id="jpa_overview_em_locking"> <title> Entity Locking </title> <indexterm zone="jpa_overview_em_locking"> <primary> EntityManager </primary> <secondary> locking </secondary> </indexterm> <para> In the area of concurrency control, the JPA specification supports optimistic and pessimistic locking. </para> <programlisting> public void lock(Object entity, LockModeType mode); </programlisting> <para> <indexterm> <primary> EntityManager </primary> <secondary> lock </secondary> </indexterm> <indexterm> <primary> locking </primary> <seealso> EntityManager </seealso> </indexterm> This method locks the given entity using the named mode. The <ulink url="http://download.oracle.com/javaee/6/api/javax/persistence/LockModeType.html"> <classname>jakarta.persistence.LockModeType</classname></ulink> enum defines eight modes: </para> <itemizedlist> <listitem> <para> <literal>OPTIMISTIC</literal>: Optimistic locking. </para> </listitem> <listitem> <para> <literal>OPTIMISTIC_FORCE_INCREMENT</literal>: Optimistic locking. When a transaction is committed, the entity's version column will be incremented even if the entity's state did not change in the transaction. </para> </listitem> <listitem> <para> <literal>PESSIMISTIC_READ</literal>: Pessimistic locking. Other transactions may concurrently read the entity, but cannot concurrently update it. </para> </listitem> <listitem> <para> <literal>PESSIMISTIC_WRITE</literal>: Pessimistic locking. Other transactions cannot concurrently read or write the entity. </para> </listitem> <listitem> <para> <literal>PESSIMISTIC_FORCE_INCREMENT</literal>: Pessimistic locking. Other transactions cannot concurrently read or write the entity. When a transaction is committed, the entity's version column will be incremented even if the entity's state did not change in the transaction. </para> </listitem> <listitem> <para> <literal>READ</literal>: A synonym for <literal>OPTIMISTIC</literal>. </para> </listitem> <listitem> <para> <literal>WRITE</literal>: A synonym for <literal>OPTIMISTIC_FORCE_INCREMENT</literal>. </para> </listitem> <listitem> <para> <literal>NONE</literal>: No locking is performed. </para> </listitem> </itemizedlist> <para> Entities can also be locked at the time when entity state gets loaded from the datastore. This is achieved by supplying a lock mode to the respective versions of <methodname>find</methodname> and <methodname>refresh</methodname> methods. If an entity state is to be loaded by a query, a lock mode can be passed to the <methodname>Query.setLockMode</methodname> and <methodname>TypedQuery.setLockMode</methodname> methods. </para> <programlisting> public LockModeType getLockMode(Object entity); </programlisting> <para> Returns the lock mode currently held by the given entity. </para> <note> <itemizedlist> <listitem> <para> OpenJPA differentiates between <literal>PESSIMISTIC_READ</literal> and <literal>PESSIMISTIC_WRITE</literal> lock modes only with DB2 databases. While running with other databases, there is no distinction between these two modes because <literal>PESSIMISTIC_READ</literal> lock mode is upgraded to <literal>PESSIMISTIC_WRITE</literal>. </para> </listitem> <listitem> <para> OpenJPA has additional APIs for controlling entity locking. See <xref linkend="ref_guide_locking"/> in the Reference Guide for details. </para> </listitem> </itemizedlist> </note> </section> <section id="jpa_overview_em_properties"> <title> Retrieving Properties Information </title> <indexterm zone="jpa_overview_em_properties"> <primary> EntityManager </primary> <secondary> properties information </secondary> </indexterm> &properties_info.xml; </section> <section id="jpa_overview_em_closing"> <title> Closing </title> <indexterm zone="jpa_overview_em_closing"> <primary> EntityManager </primary> <secondary> closing </secondary> </indexterm> <programlisting> public boolean isOpen(); public void close(); </programlisting> <para> When an <classname>EntityManager</classname> is no longer needed, you should call its <methodname>close</methodname> method. Closing an <classname> EntityManager</classname> releases any resources it is using. The persistence context ends, and the entities managed by the <classname>EntityManager </classname> become detached. Any <classname>Query</classname> instances the <classname>EntityManager</classname> created become invalid. Calling any method other than <methodname>isOpen</methodname> on a closed <classname>EntityManager </classname> results in an <classname>IllegalStateException</classname>. You cannot close a <classname>EntityManager</classname> that is in the middle of a transaction. </para> <para> If you are in a managed environment using injected entity managers, you should not close them. </para> </section> </chapter>