I am using JPA in a web application running in Tomcat 8. I am relatively new to JPA, and am having a hard time figuring out how to properly design my web app to use EntityManager. I have read "Java Persistence with Hibernate" and "Pro JPA 2", as well as a few posts about Entity Managers, but I am still unclear as to how to properly design my web app.
Should I create a singleton EntityManager that is used by the web app to service all requests, such as to CRUD (create, read, update, delete) entities?
Or should I ask the EntityManagerFactory to create a new EntityManager for each user request that comes in and close the EntityManager when I'm done processing the request?
I'm currently doing development on my local machine, where I am the only user.
What are the pros/cons of each approach?
Do both scale to hundreds of users?
I don't have the real world experience to answer these questions, so I'm looking for some answers/guidance from people who've used JPA in enterprise business apps.
Thanks
I have created ScopedEntityManager wrapper to ease JPA use in a servlet webapp. It creates an auto managed EM for the http request using a threadlocal variable.
It makes sure EM is rollbacked+closed after a servlet request. Same EM is returned in a getter method for the same request thread. You just need to commit() if all is good. Throwing an exception is not a problem because the request listener take care of the rollback().
See this how to instantiate a EM wrapper and life cycle manager.
https://github.com/Murmur/ScopedEntityManager/blob/master/src/es/claro/persistence/ScopedContextListener.java
https://github.com/Murmur/ScopedEntityManager
https://github.com/Murmur/ScopedEntityManager/blob/master/example_webapp/webapp/jpa1.jsp
So yes create a new EntityManager for each http request.
Related
I have a spring mvc application that I am using Hibernate with.
I am using the sessionFactory.getCurrentSession in my Dao methods (not hibernate support).
What I want to know is, what do I have to do to be able to use my hibernate database layer
in a non-web application?
I have a stand-alone java application (that runs via main) where I load spring's application context
programatically and then get my service layer (which depends on my hibernate db layer).
Do I need to do anything special in my spring.xml file to setup hibernate's session?
In my spring mvc web app, I did annotate my Dao methods with the #Transactional annotation.
(I want the transaction on a per call basis, not for a group of db calls).
P.S In my web app, how are sessions created/destroyed, is it per request?
You can get hold of the spring ApplicationContext from main method. it will behave exactly the same as the one in web.
ApplicationContext context = new ClassPathXmlApplicationContext("applicationContext.xml");
YourDAO yDao = (YourDAO)context.getBean("yourDAO");
yDao.callYourSpecialMethod();
So, from this point there is no dependancy for hibernate, it should work automatically. here just the view gets changed, no logical or structural changes. So the transactions and other things should work as usual.
I am currently having a problem with understanding a concept of JPA.
I am currently using/developing recent EclipseLink, Glassfish, Derby database to demonstrate a project.
Before I develop something in much bigger picture, I need to be absolutely sure of how this PersistingUnit work in terms of different scopes.
I have bunch of servlets 3.0 and currently saving user's associated entity classes in the request.session object (everything in the same war file). I am currently using Application-managed EntityManager using EntityManagerFactory and UserTransaction injection. It works smooth when it is tested by myself. The different versions of entities occur when 2 people accessing the same entities at the same time. I want to work with managed beans cross the same WAR, same persistence unit if possible.
I have read http://docs.oracle.com/javaee/6/tutorial/doc/bnbqw.html and bunch of explanations of those scopes which don't make sense at all for me.
Long story short, what are the usage and difference of app and container managed EntityManagers?
When you say application managed transaction it means its your code which is supposed to handle the transaction. In a nutshell it means:
You call:
entityManager.getTransaction().begin(); //to start a transaction
then if success you will ensure to call
entityManager.getTranasaction().commit(); //to commit changes to database
or in case of failure you will make sure to call:
entityManager.getTransaction().rollBack();
Now imagine you have a container, which knows when to call begin(), commit() or rollback(), thats container managed transaction. Someone taking care of transaction on your behalf.
You just need to specify that.
Container managed transaction(CMT) could be regarded as a kind of declarative transaction, in which case, transaction management is delegated to container (normally EJB container), and much development work could be simplified.
If we are in a Java EE environment with an EJB container, we could use CMT directly.
If we are in a Java SE environment, or a Java EE environment without an EJB container, we could still take advantage of CMT, one way is to use Spring, which uses AOP to implement declarative transaction management; Another way is to use Guice, which uses a PersistFilter to implement declarative transaction.
In CMT, a container (whatever an EJB container, Spring or Guice) will take care of the transaction propagation and commit/rollback stuff;
Application managed transaction (AMT) differs from CMT in that we need to handle transactions programmatically in our code.
I am working currently on creation of some tests on my app.
I have faced an issue which needs to involve #PrePersist feature from JPA.
Unfortunately those interceptors aren't fired, while persisting, updating ( etc ) and I found that with Session API of Hibernate this feature does not work. Here appears my question.
What is the main prove that Session API is used in the app, and is there a chance to retrieve directly EntityManager so the triggers are fired ?
I greatly appreciate any hints and advice on this topic,
What is the main prove that Session API is used in the app
Oversimplifying, the EntityManager API is a "shell" around the original Session API. But I think you want another answer :-) The only other answer I can give is to check the source code. Or, if you don't have the source code, you'll want to change the logging configuration. Set it to "trace" for the Session class, then you can see exactly when it's being called.
and is there a chance to retrieve directly EntityManager so the triggers are fired ?
Sure, depending on the application server or framework you are using. If you have a "real" application server, you can retrieve the EM from it. If you are using a standalone application, you can use the EntityManagerFactory to create a EntityManager. But before doing that, I would check the examples in the Hibernate test suite:
https://github.com/hibernate/hibernate-core/blob/master/hibernate-entitymanager/src/test/java/org/hibernate/ejb/test/LastUpdateListener.java
Also, if you are not using the JPA API, you can still have event listeners in Hibernate:
http://docs.jboss.org/hibernate/core/3.6/reference/en-US/html_single/#objectstate-events
when using hibernate with spring, can someone explain how the session unit of work and transactions are handled?
is the transaction started at the beginning of the page request, and committed at the end?
can I have multiple db calls per request, that each have different transaction levels? e.g. some are left as default, while others are read-uncommitted?
is the transaction started at the beginning of the page request, and committed at the end?
In a web application, opening / closing the Session is usually done using the "Open Session in View" pattern. Spring comes with a OpenSessionInViewFilter or an OpenSessionInViewInterceptor for this. Both make Hibernate Sessions available via the current thread, which will be autodetected by transaction managers. It is suitable for service layer transactions via HibernateTransactionManager or JtaTransactionManager as well as for non-transactional execution (if configured appropriately).
Transaction demarcation is usually done at the service methods level, using Spring AOP to wrap them inside transactions.
can I have multiple db calls per request, that each have different transaction levels? e.g. some are left as default, while others are read-uncommitted?
You can have nested transactions with different isolation levels. Refer to the Transaction Management chapter.
It's usually configured declaratively with aspect oriented programming (AOP). You can define what beans, classes, packages or methods require transactions and Spring will provide it in a fashion similar to EJBs. Thanks to AOP you have full control over what exactly and how is wrapped into transactions.
Read more about it here: http://static.springsource.org/spring/docs/3.0.x/spring-framework-reference/html/transaction.html#transaction-declarative
to your questions:
1-is the transaction started at the
beginning of the page request, and
committed at the end?
Not exactly. the usual workflow of spring MVC is:
requestDispatcher->Controller->Service call(transaction starts and ends here)
Services may invoke Daos, Daos will talk to Datastore via Hibernate.
A transaction can continue living after the http response. e.g. service run in a thread.
2-can I have multiple db calls per
request, that each have different
transaction levels? e.g. some are left
as default, while others are
read-uncommitted?
Yes certainly you can.
let's say, your application does a migration job. a request says "start migration!" Then your service will read data via source database, and do some magic base on your migration logic, finally write to target database, and commit the transaction.
I came aboard a new project with a new company and we are trying to use JPA to do some DB work. So we have an Ear with an EJB, a webservice, and then there is a app client in the ear that really does all the work. The Webservice, calls the EJB, and the EJB calls the client to do the DB work. So within the appclient I want to load an EntityManager via annotations, but it does not seem to work (em is always null):
#Entity
public class Whatever...{
#PersistenceContext(unitName="pu")
EntityManager em;
}
So I was thinking that I need to load the EntityManager at the EJB, but that didn't work either, because it seems that JPA didn't see the Entity classes since they are in the appclient and not the EJB. Can anyone give me some guidance?
This is a misuse of an app client. All your db processing should occur in the EJB. There doesn't seem to be any apparent reason for the app clients' existence.
This link is to an old article, but gives examples as to what an app client is used for (Applications not backend services).
Application Client