In the persistence.xml JPA configuration file, you can have a line like:
<persistence-unit name="com.nz_war_1.0-SNAPSHOTPU" transaction-type="JTA">
or sometimes:
<persistence-unit name="com.nz_war_1.0-SNAPSHOTPU" transaction-type=”RESOURCE_LOCAL”>
My question is:
What is the difference between transaction-type="JTA" and transaction-type=”RESOURCE_LOCAL” ?
I also noticed some persistence.xml files with the transaction-type missing. Is it correct?
Defaults
Default to JTA in a JavaEE environment and to RESOURCE_LOCAL in a JavaSE environment.
RESOURCE_LOCAL
With <persistence-unit transaction-type="RESOURCE_LOCAL"> you are responsible for EntityManager (PersistenceContext/Cache) creating and tracking
You must use the EntityManagerFactory to get an EntityManager
The resulting EntityManager instance is a PersistenceContext/Cache
An EntityManagerFactory can be injected via the #PersistenceUnit annotation only (not #PersistenceContext)
You are not allowed to use #PersistenceContext to refer to a unit of type RESOURCE_LOCAL
You must use the EntityTransaction API to begin/commit around every call to your EntityManger
Calling entityManagerFactory.createEntityManager() twice results in two separate EntityManager instances and therefor two separate PersistenceContexts/Caches.
It is almost never a good idea to have more than one instance of an EntityManager in use (don't create a second one unless you've destroyed the first)
JTA
With <persistence-unit transaction-type="JTA"> the container will do EntityManager (PersistenceContext/Cache) creating and tracking.
You cannot use the EntityManagerFactory to get an EntityManager
You can only get an EntityManager supplied by the container
An EntityManager can be injected via the #PersistenceContext annotation only (not #PersistenceUnit)
You are not allowed to use #PersistenceUnit to refer to a unit of type JTA
The EntityManager given by the container is a reference to the PersistenceContext/Cache associated with a JTA Transaction.
If no JTA transaction is in progress, the EntityManager cannot be used because there is no PersistenceContext/Cache.
Everyone with an EntityManager reference to the same unit in the same transaction will automatically have a reference to the same PersistenceContext/Cache
The PersistenceContext/Cache is flushed and cleared at JTA commit time
Related
I'm trying to develop a simple JSP based web application with JPA and would like to know the correct usage for developing one.
In my sample application I have two JSP pages and a simple Java class to perform database operations. Both the JSP files use this Java class to perform DB operations.
I've annotated this class with #Stateless and injected an Entity manager as follows:
#PersistenceContext(unitName = "myjpa")
EntityManager em;
In my persistence.xml I've set the following property:
<property
name="hibernate.transaction.jta.platform"
value="org.hibernate.service.jta.platform.internal.JBossAppServerJtaPlatform"
/>
I'm calling the class in JSP using JNDI (as the class is annotated for a stateless session bean) as follows:
InitialContext ic = new InitialContext();
Sample sample = (Sample) ic.lookup("java:app/" + application.getContextPath() + "/Sample");
I'm facing the following scenarios:
When I try to use a transaction em.getTransaction().begin()/commit() for insert and update, it says can not use transaction with JTA case.
So in the constructor code of my Java class I use the following code:
Properties properties = new Properties();
properties.put("javax.persistence.transactionType", "RESOURCE_LOCAL");
emf = Persistence.createEntityManagerFactory("myjpa",properties);
em = emf.createEntityManager();
I tried to use transactions like em.getTransaction().begin()/commit().
But in this case the pages become very slow after 2-3 database update and load operations. Though I'm not getting any exception. Overall in my table I'm having less than 25 records.
To me it seems as if it is waiting internally for some operation to complete.
At the same time I also feel that the way I'm using JPA is wrong and hence soliciting advice for the correct approach for doing even simple web apps with JSP and JPA.
While I'm still exploring Java EE, in case you have any specific reference for such cases I'll like to read and look them too.
You should always strive to use JTA transactions which means the container will handle the transaction demarcations. In your case if you want to handle transactions by your self, you need to define it as a bean managed transaction. So in your EJB class, after the #Stateless annoattions, you should define the following annotation;
#TransactionManagement(TransactionManagementType.BEAN)
The usual best practice is to let the container handle the transactions, unless there is some explicit reason for you to use Bean managed transactions.
At the same time I also feel that the way I'm using JPA is wrong
Your usage indeed seems wrong. If you're using a (stateless) session bean you do not have to fiddle with em.getTransaction().begin()/commit() and you definitely don't have to use code such as Persistence.createEntityManagerFactory.
You also don't have to set the property org.hibernate.service.jta.platform.internal.JBossAppServerJtaPlatform.
A session bean automatically manages the transaction for you, and within a Java EE AS (such as JBoss AS) you don't have to configure any transaction manager or similar things.
An example:
#Stateless
public class UserDAO {
#PersistenceContext
private EntityManager entityManager;
public void add(User user) {
entityManager.persist(user);
}
}
As for the persistence.xml file, something like the following should be enough to get started:
<?xml version="1.0" encoding="UTF-8"?>
<persistence version="2.0"
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_2_0.xsd">
<persistence-unit name="somePU">
<jta-data-source>java:app/someDS</jta-data-source>
</persistence-unit>
</persistence>
Some more examples:
http://jdevelopment.nl/sample-crud-app-with-jsf-and-richfaces
http://arjan-tijms.omnifaces.org/2011/08/minimal-3-tier-java-ee-app-without-any.html
This is my first attempt at Entity beans and I repeatedly get the following error:
java.lang.IllegalStateException: Unable to retrieve EntityManagerFactory for unitName null
I wrote a simple entity beans example using a Netbeans 7.3 and GlassFish 3.1.2.2 Server. It seems there is a problem with my persistance.xml file. However, I am unable to fix this. I read up
JavaEE 6: java.lang.IllegalStateException: Unable to retrieve EntityManagerFactory for unitName null
Unable to retrieve EntityManagerFactory for unitName null for simple EJB - see nosferatum answer
But after hours also I have not quite been able to fix this. I am attaching the screenshot of my directory structure and also code for my XML file with the hope that someone can point out the mistake.
persistance.xml : ( Code autogenerated by NetBeans )
<?xml version="1.0" encoding="UTF-8"?>
<persistence version="2.0" 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_2_0.xsd">
<persistence-unit name="EnterpriseApplication3-ejbPU" transaction-type="JTA">
<jta-data-source>TestDatabase</jta-data-source>
<exclude-unlisted-classes>false</exclude-unlisted-classes>
<properties/>
</persistence-unit>
</persistence>
Failing Code :
Declaration :
// This injects the default entity manager factory
#PersistenceUnit
private EntityManagerFactory emf;
Point of Invocation :
EntityManager em = emf.createEntityManager();
Also, a few people seem to do this :
#PersistenceContext(unitName = "myPU")
and have the same name in the persistance.xml. I did a quick search of all my project files and did not come up with the #PersistenceContext annotation. But I added
#PersistenceContext(unitName = "EnterpriseApplication3-ejbPU")
to my code that calls the EntityManagerFactory. But still no success :(
try this one:
EntityManagerFactory emf = Persistence.createEntityManagerFactory("EnterpriseApplication3-ejbPU");
EntityManager em = emf.createEntityManager();
For (Glassfish v2.1), two RuntimeExceptions from two separate requests from a session bean:
"org.hibernate.SessionException: Session is closed!"
org.hibernate.SessionException: Session is closed!
at org.hibernate.impl.AbstractSessionImpl.errorIfClosed(AbstractSessionImpl.java:72)
at org.hibernate.impl.SessionImpl.list(SessionImpl.java:1138)
at org.hibernate.impl.QueryImpl.list(QueryImpl.java:102)
at org.hibernate.ejb.QueryImpl.getResultList(QueryImpl.java:67)
[wrapped] javax.persistence.PersistenceException: org.hibernate.SessionException: Session is closed!
at org.hibernate.ejb.AbstractEntityManagerImpl.throwPersistenceException(AbstractEntityManagerImpl.java:614)
at org.hibernate.ejb.QueryImpl.getResultList(QueryImpl.java:76)
"java.lang.IllegalStateException: EntityManager is closed"
java.lang.IllegalStateException: EntityManager is closed
at org.hibernate.ejb.EntityManagerImpl.close(EntityManagerImpl.java:97)
at com.sun.enterprise.util.QueryWrapper.clearDelegates(QueryWrapper.java:460)
at com.sun.enterprise.util.QueryWrapper.getResultList(QueryWrapper.java:198)
Both of these EntityManagers were obtained via JNDI lookup (java:comp:/env/TargetSitePersistenceContext)
Using JTA (transaction-type attribute is not defined in persistence.xml).
& SQL Server 2008 w/ sqljdbc4.jar
The code just does the ff:
query = entityManager.createQuery();
query.getResultList();
And that's it. If I'm not mistaken, I believe the app container will handle open/commit/rollback/close, so we shouldn't have any entityManager.close().
What might have caused those two runtime exceptions?
When does GF actually open/close an EntityManager?
Is there any difference between:
an EntityManager obtained via JNDI lookup
via #PersistenceContext Injection? (So far not issues with this style)
All things being equal, a #PersistenceContext injection and a JNDI lookup should return the same EntityManager. So it might be a bug of GlassFish and you might want to reach for them. But make sure to give all the context like type of session bean used for injection, transaction or not etc etc.
Mark your bean with annotation #TransactionAttribute
#Stateless
#TransactionAttribute(TransactionAttributeType.MANDATORY)
public class Repo implements IRepo
{
container managed transaction is regulated by this parameter
I have the following code. The problem is that on the second line I get "org.apache.openjpa.persistence.TransactionRequiredException: Can only perform operation while a transaction is active"
The first line executed fine. What is my mistake?
//em is some EntityManager
String s = (String)em.createQuery("SELECT something FROM something WHERE something = something").getSingleResult();
em.createQuery("DELETE FROM something WHERE something = something").executeUpdate();
Read operations are handled differently from write operations in JPA. Write operations (be they create, updates or deletes) typically need to happen in the context of a transaction. The transaction boundary demarcates the calls you make to the session or entity manager, and defines when the transaction will be committed, (for example it could call commit on method call exit, when using container managed transactions).
For JPA, all calls to persist, remove, refresh and merge need to be done in a transaction. Query calls need to be performed in a transaction if they invoke executeUpdate. And calling getResultList() or getUniqueResult() needs to be done in the context of a transaction if lock mode is not LockMode.NONE.
Depending on your application needs you will use either container managed transactions (CMT), or bean managed transactions (BMT).
For CMT, make sure your persistence unit defines your datasource as JTA, and then annotate your class or method appropriately. For example:
<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_2_0.xsd"
version="2.0">
<persistence-unit name="sample" transaction-type="JTA">
<jta-data-source>java:/DefaultDS</jta-data-source>
<properties>
<property name="hibernate.dialect" value="org.hibernate.dialect.HSQLDialect"/>
<property name="hibernate.hbm2ddl.auto" value="create-drop"/>
</properties>
</persistence-unit>
</persistence>
And then annotate your class/method with the appropriate transaction type:
# TransactionAttribute(TransactionAttributeType.REQUIRED)
public void doSomething() {
em.createQuery("DELETE FROM something WHERE something = something").executeUpdate();
}
If using BMT, then you have to explicitly manage the transactions:
public void doSomething() throws Exception {
em.getTransaction().begin();
try {
em.createQuery("DELETE FROM something WHERE something = something").executeUpdate();
} catch(Exception e) {
em.getTransaction().setRollbackOnly();
} finally {
em.getTransaction().commit();
}
}
You can only modify data in the database while a transaction is active. You start a transaction with
em.getTransaction().begin();
and end it successfully with
em.getTransaction().commit();
or end it rolling back the changes with
em.getTransaction().rollback();
I'm try to use the Sun Java PetStore Demo.
In the CatalogFacade class there is the following annotation:
#PersistenceUnit(unitName="myPetStorePU")
private EntityManagerFactory emf;
In all the methods of the CatalogFacade Sun has:
EntityManager em = emf.createEntityManager();
But I am getting a null pointer exception for emf when trying to createEntityManager. But... if I add the following line above that line as such
EntityManagerFactory emf = javax.persistence.Persistence.createEntityManagerFactory("myPetStorePU");
EntityManager em = emf.createEntityManager();
then emf gets successfully created and the persistence unit myPetStorePU also successfully connects to the database. So it looks like persistence.xml syntax and its location is correct. I'd like to understand why the annotation doesn't work since I think there was a reason for just using the annotation as opposed to adding the createEntityManagerFactory line in every method.
My src/META-INF/persistence.xml file looks like this:
<persistence-unit name="myPetStorePU">
<description>Petstore Persistence Unit</description>
<provider>oracle.toplink.essentials.ejb.cmp3.EntityManagerFactoryProvider</provider>
<class>com.sun.javaee.blueprints.petstore.model.Tag</class>
<class>com.sun.javaee.blueprints.petstore.model.SellerContactInfo</class>
<class>com.sun.javaee.blueprints.petstore.model.Product</class>
<class>com.sun.javaee.blueprints.petstore.model.Item</class>
<class>com.sun.javaee.blueprints.petstore.model.Category</class>
<class>com.sun.javaee.blueprints.petstore.model.Address</class>
<class>com.sun.javaee.blueprints.petstore.model.ZipLocation</class>
<properties>
<property name="toplink.jdbc.driver" value="oracle.jdbc.driver.OracleDriver"/>
<property name="toplink.jdbc.url" value="jdbc:oracle:thin:##############"/>
<property name="toplink.jdbc.user" value="####"/>
<property name="toplink.jdbc.password" value="#####"/>
<property name="toplink.logging.level" value="INFO"/>
</properties>
</persistence-unit>
Edit:
CatalogFacade is in the petstore.model package and implements the ServletContextListener
<listener>
<listener-class>com.sun.javaee.blueprints.petstore.model.CatalogFacade</listener-class>
</listener>
in the index.jsp Sun has the following:
<%
CatalogFacade cf = (CatalogFacade)config.getServletContext().getAttribute("CatalogFacade");
List<Tag> tags=cf.getTagsInChunk(0, 12);
%>
public List<Tag> getTagsInChunk(int start, int chunkSize) {
//The next line is required since the #PersistenceUnit annotation at the top of this class does not work
EntityManagerFactory emf = javax.persistence.Persistence.createEntityManagerFactory("myPetStorePU");
EntityManager em = emf.createEntityManager();
System.out.println("Entity manager " + emf);
Query query = em.createQuery("SELECT t FROM Tag t ORDER BY t.refCount DESC, t.tag");
List<Tag> tags = query.setFirstResult(start).setMaxResults(chunkSize).getResultList();
em.close();
return tags;
}
If the annotated object is not managed by a container (either spring/CDI/EJB container), nothing gets injected into it.
So depending on your environment, obtain a contextual instance of that object.
If you are not using any of the above technologies (spring/CDI/EJB) - then you can't use #PersistenceUnit and #PersistenceContext. Use the manual way to obtain the unit.
For some reasons this happens when using this in you persistence.xml
<provider>org.hibernate.ejb.HibernatePersistence</provider>
switching to
<provider>org.eclipse.persistence.jpa.PersistenceProvider</provider>
fixes the problem