| <!DOCTYPE html> |
| <html lang="en"> |
| <head> |
| |
| <meta charset="UTF-8"> |
| <title>JPA Concepts</title> |
| <meta name="description" content="Apache TomEE"> |
| <meta name="author" content="Apache TomEE"> |
| <meta name="google-translate-customization" content="f36a520c08f4c9-0a04e86a9c075ce9-g265f3196f697cf8f-10"> |
| <meta http-equiv="Pragma" content="no-cache"> |
| <meta http-equiv="Expires" content="0"> |
| <meta http-equiv="Cache-Control" content="no-store, no-cache, must-revalidate, max-age=0"> |
| |
| <!-- Le HTML5 shim, for IE6-8 support of HTML elements --> |
| <!--[if lt IE 9]> |
| <script src="http://html5shim.googlecode.com/svn/trunk/html5.js"></script> |
| <![endif]--> |
| |
| <!-- Le styles --> |
| <link href="./resources/css/bootstrap.css" rel="stylesheet"> |
| <link href="./resources/css/prettify.css" rel="stylesheet"> |
| <!--link href="./resources/css/bootstrap-mods.css" rel="stylesheet"--> |
| <link href="./resources/css/main.css" rel="stylesheet"> |
| <link href="./resources/font-awesome-4.6.3/css/font-awesome.min.css" rel="stylesheet"> |
| |
| <script type="text/javascript"> |
| var t = encodeURIComponent(document.title.replace(/^\s+|\s+$/g,"")); |
| var u = encodeURIComponent(""+document.URL); |
| |
| function fbshare () { |
| window.open( |
| "http://www.facebook.com/sharer/sharer.php?u="+u, |
| 'Share on Facebook', |
| 'width=640,height=426'); |
| }; |
| function gpshare () { |
| window.open( |
| "https://plus.google.com/share?url="+u, |
| 'Share on Google+', |
| 'width=584,height=385'); |
| }; |
| function twshare () { |
| window.open( |
| "https://twitter.com/intent/tweet?url="+u+"&text="+t, |
| 'Share on Twitter', |
| 'width=800,height=526'); |
| }; |
| function pinshare () { |
| window.open("//www.pinterest.com/pin/create/button/?url="+u+"&media=http%3A%2F%2Ftomee.apache.org%2Fresources%2Fimages%2Ffeather-logo.png&description="+t, |
| 'Share on Pinterest', |
| 'width=800,height=526'); |
| }; |
| </script> |
| |
| <!-- Le fav and touch icons --> |
| <link rel="shortcut icon" href="./favicon.ico"> |
| <link rel="apple-touch-icon" href="./resources/images/apple-touch-icon.png"> |
| <link rel="apple-touch-icon" sizes="72x72" href="./resources/images/apple-touch-icon-72x72.png"> |
| <link rel="apple-touch-icon" sizes="114x114" href="./resources/images/apple-touch-icon-114x114.png"> |
| |
| <script src="./resources/js/prettify.js" type="text/javascript"></script> |
| <script src="./resources/js/jquery-latest.js"></script> |
| <script src="http://platform.twitter.com/widgets.js" type="text/javascript"></script> |
| <script src="./resources/js/common.js"></script> |
| <script src="./resources/js/prettyprint.js"></script> |
| <!--script src="//assets.pinterest.com/js/pinit.js" type="text/javascript" async></script//--> |
| |
| <script type="text/javascript"> |
| |
| var _gaq = _gaq || []; |
| _gaq.push(['_setAccount', 'UA-2717626-1']); |
| _gaq.push(['_setDomainName', 'apache.org']); |
| _gaq.push(['_trackPageview']); |
| |
| (function() { |
| var ga = document.createElement('script'); ga.type = 'text/javascript'; ga.async = true; |
| ga.src = ('https:' == document.location.protocol ? 'https://ssl' : 'http://www') + '.google-analytics.com/ga.js'; |
| var s = document.getElementsByTagName('script')[0]; s.parentNode.insertBefore(ga, s); |
| })(); |
| |
| </script> |
| </head> |
| |
| <body> |
| |
| <div class="topbar" data-dropdown="dropdown"> |
| <div class="fill"> |
| <div class="container"> |
| <a class="brand" href="./index.html">Apache TomEE</a> |
| <ul class="nav"> |
| <li class="dropdown"> |
| <a class="dropdown-toggle" data-toggle="dropdown" href="#"> |
| Apache |
| <b class="caret"></b> |
| </a> |
| <ul class="dropdown-menu"> |
| <!-- <li><a href="./misc/whoweare.html">Who we are?</a></li> --> |
| <!-- <li><a href="./misc/heritage.html">Heritage</a></li> --> |
| <li><a href="http://www.apache.org">Apache Home</a></li> |
| <!-- <li><a href="./misc/resources.html">Resources</a></li> --> |
| <li><a href="./misc/contact.html">Contact</a></li> |
| <li><a href="./misc/legal.html">Legal</a></li> |
| <li><a href="http://www.apache.org/foundation/sponsorship.html">Sponsorship</a></li> |
| <li><a href="http://www.apache.org/foundation/thanks.html">Thanks</a></li> |
| <li class="divider"/> |
| <li><a href="http://www.apache.org/security">Security</a></li> |
| </ul> |
| </li> |
| <li><a href="./index.html">Home</a></li> |
| <li><a href="./downloads.html">Downloads</a></li> |
| <li><a href="./documentation.html">Documentation</a></li> |
| <li><a href="./examples-trunk/index.html">Examples</a></li> |
| <li><a href="./support.html">Support</a></li> |
| <li><a href="./contribute.html">Contribute</a></li> |
| <li><a href="./security/index.html">Security</a></li> |
| </ul> |
| |
| <!-- Google CSE Search Box Begins --> |
| <FORM class="pull-right" id="searchbox_010475492895890475512:_t4iqjrgx90" action="http://www.google.com/cse"> |
| <INPUT type="hidden" name="cx" value="010475492895890475512:_t4iqjrgx90"> |
| <INPUT type="hidden" name="cof" value="FORID:0"> |
| <INPUT size="18" width="130" style="width:130px" name="q" type="text" placeholder="Search"> |
| </FORM> |
| <!--<SCRIPT type="text/javascript" src="http://www.google.com/coop/cse/brand?form=searchbox_010475492895890475512:_t4iqjrgx90"></SCRIPT>--> |
| <!-- Google CSE Search Box Ends --> |
| </div> |
| </div> |
| </div> |
| |
| <div class="container"> |
| |
| |
| <div class="page-header"> |
| <small><a href="./index.html">Home</a></small><br> |
| <h1>JPA Concepts |
| |
| <div style="float: right; position: relative; bottom: -10px; "> |
| <a onclick="javascript:gpshare()" class="gp-share sprite" title="Share on Google+">share [gp]</a> |
| <a onclick="javascript:fbshare()" class="fb-share sprite" title="Share on Facebook">share [fb]</a> |
| <a onclick="javascript:twshare()" class="tw-share sprite" title="Share on Twitter">share [tw]</a> |
| <a onclick="javascript:pinshare()" class="pin-share sprite" title="Share on Pinterest">share [pin]</a> |
| <a data-toggle="modal" href="#edit" class="edit-page" title="Contribute to this Page">contribute</a> |
| </div> |
| </h1> |
| </div> |
| |
| <p><a name="JPAConcepts-JPA101"></a></p> |
| |
| <h1>JPA 101</h1> |
| |
| <p>If there's one thing you have to understand to successfully use JPA (Java |
| Persistence API) it's the concept of a <em>Cache</em>. Almost everything boils |
| down to the Cache at one point or another. Unfortunately the Cache is an |
| internal thing and not exposed via the JPA API classes, so it not easy to |
| touch or feel from a coding perspective.</p> |
| |
| <p>Here's a quick cheat sheet of the JPA world:</p> |
| |
| <ul> |
| <li>A <strong>Cache</strong> is a <strong>copy of data</strong>, copy meaning pulled from but living |
| outside the database.</li> |
| <li><strong>Flushing</strong> a Cache is the act of putting modified data back into the |
| database.</li> |
| <li>A <strong>PersistenceContext</strong> is essentially a Cache. It also tends to have |
| it's own non-shared database connection.</li> |
| <li>An <strong>EntityManager</strong> represents a PersistenceContext (and therefore a |
| Cache)</li> |
| <li>An <strong>EntityManagerFactory</strong> creates an EntityManager (and therefore a |
| PersistenceContext/Cache)</li> |
| </ul> |
| |
| <p>Comparing <code>RESOURCE_LOCAL</code> and <code>JTA</code> persistence contexts</p> |
| |
| <p>With <persistence-unit transaction-type="<strong>RESOURCE_LOCAL</strong>"> <strong>you</strong> are |
| responsible for EntityManager (PersistenceContext/Cache) creating and |
| tracking...</p> |
| |
| <ul> |
| <li>You <strong>must</strong> use the <strong>EntityManagerFactory</strong> to get an EntityManager</li> |
| <li>The resulting <strong>EntityManager</strong> instance <strong>is</strong> a |
| PersistenceContext/Cache</li> |
| <li>An <strong>EntityManagerFactory</strong> can be injected via the <strong>@PersistenceUnit</strong> |
| annotation only (not @PersistenceContext)</li> |
| <li>You are <strong>not</strong> allowed to use @PersistenceContext to refer to a unit |
| of type RESOURCE_LOCAL</li> |
| <li>You <strong>must</strong> use the <strong>EntityTransaction</strong> API to begin/commit around |
| <strong>every</strong> call to your EntityManger</li> |
| <li>Calling entityManagerFactory.createEntityManager() twice results in |
| <strong>two</strong> separate EntityManager instances and therefor <strong>two</strong> separate |
| PersistenceContexts/Caches.</li> |
| <li>It is <strong>almost never</strong> a good idea to have more than one <strong>instance</strong> of |
| an EntityManager in use (don't create a second one unless you've destroyed |
| the first)</li> |
| </ul> |
| |
| <p>With <persistence-unit transaction-type="<strong>JTA</strong>"> the <strong>container</strong> |
| will do EntityManager (PersistenceContext/Cache) creating and tracking...</p> |
| |
| <ul> |
| <li>You <strong>cannot</strong> use the <strong>EntityManagerFactory</strong> to get an EntityManager</li> |
| <li>You can only get an <strong>EntityManager</strong> supplied by the <strong>container</strong></li> |
| <li>An <strong>EntityManager</strong> can be injected via the <strong>@PersistenceContext</strong> |
| annotation only (not @PersistenceUnit)</li> |
| <li>You are <strong>not</strong> allowed to use @PersistenceUnit to refer to a unit of |
| type JTA</li> |
| <li>The <strong>EntityManager</strong> given by the container is a <strong>reference</strong> to the |
| PersistenceContext/Cache associated with a JTA Transaction.</li> |
| <li>If no JTA transaction is in progress, the EntityManager <strong>cannot be |
| used</strong> because there is no PersistenceContext/Cache.</li> |
| <li>Everyone with an EntityManager reference to the <strong>same unit</strong> in the |
| <strong>same transaction</strong> will automatically have a reference to the <strong>same |
| PersistenceContext/Cache</strong></li> |
| <li>The PersistenceContext/Cache is <strong>flushed</strong> and cleared at JTA |
| <strong>commit</strong> time</li> |
| </ul> |
| |
| <p><a name="JPAConcepts-Cache==PersistenceContext"></a></p> |
| |
| <h1>Cache == PersistenceContext</h1> |
| |
| <p>The concept of a database cache is an extremely important concept to be |
| aware of. Without a copy of the data in memory (i.e. a cache) when you |
| call account.getBalance() the persistence provider would have to go read |
| the value from the database. Calling account.getBalance() several times |
| would cause several trips to the database. This would obviously be a big |
| waste of resources. The other side of having a cache is that when you call |
| account.setBalance(5000) it also doesn't hit the database (usually). When |
| the cache is "flushed" the data in it is sent to the database via as many |
| SQL updates, inserts and deletes as are required. That is the basics of |
| java persistence of any kind all wrapped in a nutshell. If you can |
| understand that, you're good to go in nearly any persistence technology |
| java has to offer.</p> |
| |
| <p>Complications can arise when there is more than one |
| PersistenceContext/Cache relating the same data in the same transaction. |
| In any given transaction you want exactly one PersistenceContext/Cache for |
| a given set of data. Using a JTA unit with an EntityManager |
| created by the container will always guarantee that this is the case. With |
| a RESOURCE_LOCAL unit and an EntityManagerFactory you should create and use |
| exactly one EntityManager instance in your transaction to ensure there is |
| only one active PersistenceContext/Cache for the given set of data active |
| against the current transaction.</p> |
| |
| <p><a name="JPAConcepts-CachesandDetaching"></a></p> |
| |
| <h1>Caches and Detaching</h1> |
| |
| <p>Detaching is the concept of a persistent object <strong>leaving</strong> the |
| PersistenceContext/Cache. Leaving means that any updates made to the |
| object are <strong>not</strong> reflected in the PersistenceContext/Cache. An object will |
| become Detached if it somehow <strong>lives longer</strong> or is <strong>used outside</strong> the scope |
| of the PersistenceContext/Cache. </p> |
| |
| <p>For a JTA unit, the PersistenceContext/Cache will live as long as |
| the transaction does. When a transaction completes (commits or rollsback) |
| all objects that were in the PersistenceContext/Cache are Detached. You |
| can still use them, but they are no longer associated with a |
| PersistenceContext/Cache and modifications on them will <strong>not</strong> be reflected |
| in a PersistenceContext/Cache and therefore not the database either.</p> |
| |
| <p>Serializing objects that are currently in a PersistenceContext/Cache will |
| also cause them to Detach.</p> |
| |
| <p>In some cases objects or collections of objects that become Detached may |
| not have all the data you need. This can be because of lazy loading. With |
| lazy loading, data isn't pulled from the database and into the |
| PersistenceContext/Cache until it is requested in code. In many cases the |
| Collections of persistent objects returned from an |
| javax.persistence.Query.getResultList() call are completely empty until you |
| iterate over them. A side effect of this is that if the Collection becomes |
| Detached before it's been fully read it will be permanently empty and of no |
| use and calling methods on the Detached Collection can cause strange errors |
| and exceptions to be thrown. If you wish to Detach a Collection of |
| persistent objects it is always a good idea to iterate over the Collection |
| at least once.</p> |
| |
| <p>You <strong>cannot</strong> call EntityManager.persist() or EntityManager.remove() on a |
| Detached object.</p> |
| |
| <p>Calling EntityManager.merge() will re-attach a Detached object.</p> |
| |
| <p><a name="JPAConcepts-ValidRESOURCE_LOCALUnitusage"></a></p> |
| |
| <h1>Valid RESOURCE_LOCAL Unit usage</h1> |
| |
| <p>Servlets and EJBs can use RESOURCE_LOCAL persistence units through the |
| EntityManagerFactory as follows:</p> |
| |
| <pre><code><?xml version="1.0" encoding="UTF-8" ?> |
| <persistence xmlns="http://java.sun.com/xml/ns/persistence" version="1.0"> |
| |
| <!-- Tutorial "unit" --> |
| <persistence-unit name="Tutorial" transaction-type="RESOURCE_LOCAL"> |
| <non-jta-data-source>myNonJtaDataSource</non-jta-data-source> |
| <class>org.superbiz.jpa.Account</class> |
| </persistence-unit> |
| |
| </persistence> |
| </code></pre> |
| |
| <p>And referenced as follows</p> |
| |
| <pre><code>import javax.persistence.EntityManagerFactory; |
| import javax.persistence.EntityManager; |
| import javax.persistence.EntityTransaction; |
| import javax.persistence.PersistenceUnit; |
| |
| public class MyEjbOrServlet ... { |
| |
| @PersistenceUnit(unitName="Tutorial") |
| private EntityManagerFactory factory; |
| |
| // Proper exception handling left out for simplicity |
| public void ejbMethodOrServletServiceMethod() throws Exception { |
| EntityManager entityManager = factory.createEntityManager(); |
| |
| EntityTransaction entityTransaction = entityManager.getTransaction(); |
| |
| entityTransaction.begin(); |
| |
| Account account = entityManager.find(Account.class, 12345); |
| |
| account.setBalance(5000); |
| |
| entityTransaction.commit(); |
| } |
| |
| ... |
| } |
| </code></pre> |
| |
| <h1>Valid JTA Unit usage</h1> |
| |
| <p>EJBs can use JTA persistence units through the EntityManager as |
| follows:</p> |
| |
| <pre><code><?xml version="1.0" encoding="UTF-8" ?> |
| <persistence xmlns="http://java.sun.com/xml/ns/persistence" version="1.0"> |
| |
| <!-- Tutorial "unit" --> |
| <persistence-unit name="Tutorial" transaction-type="JTA"> |
| <jta-data-source>myJtaDataSource</jta-data-source> |
| <non-jta-data-source>myNonJtaDataSource</non-jta-data-source> |
| <class>org.superbiz.jpa.Account</class> |
| </persistence-unit> |
| |
| </persistence> |
| </code></pre> |
| |
| <p>And referenced as follows</p> |
| |
| <pre><code>import javax.ejb.Stateless; |
| import javax.ejb.TransactionAttribute; |
| import javax.ejb.TransactionAttributeType; |
| import javax.persistence.EntityManager; |
| import javax.persistence.PersistenceContext; |
| |
| @Stateless |
| public class MyEjb implements MyEjbInterface { |
| |
| @PersistenceContext(unitName = "Tutorial") |
| private EntityManager entityManager; |
| |
| // Proper exception handling left out for simplicity |
| @TransactionAttribute(TransactionAttributeType.REQUIRED) |
| public void ejbMethod() throws Exception { |
| |
| Account account = entityManager.find(Account.class, 12345); |
| |
| account.setBalance(5000); |
| |
| } |
| } |
| </code></pre> |
| |
| |
| |
| |
| <div id="edit" class="modal hide fade in" style="display: none; "> |
| <div class="modal-header"> |
| <a class="close" data-dismiss="modal">x</a> |
| |
| <h3>Thank you for contributing to the documentation!</h3> |
| </div> |
| <div class="modal-body"> |
| <h4>Any help with the documentation is greatly appreciated.</h4> |
| <p>All edits are reviewed before going live, so feel free to do much more than fix typos or links. If you see a page that could benefit from an entire rewrite, we'd be thrilled to review it. Don't be surprised if we like it so much we ask you for help with other pages :)</p> |
| <small>NOTICE: unless indicated otherwise on the pages in question, all editable content available from apache.org is presumed to be licensed under the Apache License (AL) version 2.0 and hence all submissions to apache.org treated as formal Contributions under the license terms.</small> |
| <!--[if gt IE 6]> |
| <h4>Internet Explorer Users</h4> |
| <p>If you are not an Apache committer, click the Yes link and enter a <i>anonymous</i> for the username and leave the password empty</p> |
| <![endif]--> |
| |
| </div> |
| <div class="modal-footer"> |
| Do you have an Apache ID? |
| <a href="javascript:void(location.href='https://cms.apache.org/redirect?uri='+escape(location.href))" class="btn">Yes</a> |
| <a href="javascript:void(location.href='https://anonymous:@cms.apache.org/redirect?uri='+escape(location.href))" class="btn">No</a> |
| </div> |
| </div> |
| <script src="./resources/js/bootstrap-modal.js"></script> |
| |
| <footer> |
| <p>Copyright © 1999-2016 The Apache Software Foundation, Licensed under the Apache License, Version 2.0. |
| Apache TomEE, TomEE, Apache, the Apache feather logo, and the Apache TomEE project logo are trademarks of The Apache Software Foundation. |
| All other marks mentioned may be trademarks or registered trademarks of their respective owners.</p> |
| </footer> |
| |
| </div> <!-- /container --> |
| |
| <!-- Javascript |
| ================================================== --> |
| <!-- Placed at the end of the document so the pages load faster --> |
| <script src="./resources/js/bootstrap-dropdown.js"></script> |
| |
| </body> |
| </html> |