Your first alternative is fine.
Don't go for the second alternative. Although that piece of code is
legal, I don't think that is what you want. There you have created two
*different* entity managers and hence you have to manage them separately
(i.e. close each of them etc.). You are transaction safe since you
created each of them after calling utx.begin(). Both of them
automatically *join* the currently active transaction and hence when you
call utx.commit(), changes made using both the ems will be committed.
But, you have to be careful in your code so that you don't accidentally
use the same managed entity in two different ems. Hence the first
alternative is better.
There is even better(recommended) alternative than both of these. In
both of the above cases, you are using application managed entity
manager. If you use container managed entity manager, then you have the
choice of either passing the em or looking it up in as many places as
you like. To achieve this, do something like this (see the use of
@PersistenceContext in class level):
@PersistenceContext(name="persistence/LogicalName", unitName="ActualPUNameAsItAppearsInPersistence.xml")
public class MyServlet extends HttpServlet {
@Resource private UserTransaction utx;
public void doGet ( HttpServletRequest req , HttpServletResponse resp)
throws ServletException, IOException {
utx.begin();
new A().saveA();
new B().saveB();
utx.commit();
}
}
class A{
void saveA() {
Context envCtx = InitialContext().lookup("java:comp/env");
*EntityManager em = (EntityManager) envCtx.lookup("persistence/LogicalName");*
em.persist(itemA);
}
}
class B{
void saveB() {
Context envCtx = InitialContext().lookup("java:comp/env");
*EntityManager em = (EntityManager) envCtx.lookup("persistence/LogicalName");*
em.persist(iteamB);
}
}
If you want, you could actually look up the em in doGet() and pass it to
saveA() and saveB(), but I don't see any benefit of doing that because
every time you look up within a given transaction context, you get the
same entity manager. Hence in the above code, saveA and saveB use same em.
Hope this answers your question.
Thanks,
Sahoo
Uwe Gerger wrote:
> Hi,
> I have the following question about using an application managed "em" in web applications.
>
> I have to call two methods of different objects in one servlet request. The two methods have to be part of one transaction.
>
> Do I have to pass the em as a parameter to each method or can I use "em=emf.createEntityManager()" in each method?
>
> For example:
>
> doGet(...)
> {
> A a = new A();
> B b = new B();
>
>
> utx.begin();
>
> em = emf.createEntityManager();
>
> a.saveA(em);
>
> b.saveB(em);
>
> utx.commit();
>
> }
>
>
> or can I use "em = emf.createEntityManager();" in each of the methods saveA and saveB so that the code snippet will look like this:
>
> doGet()
> {
> utx.begin();
>
> a.saveA();
>
> b.saveB();
>
> utx.commit();
>
> }
>
> In the methods:
> saveA()
> {
> em = emf.createEntityManager();
> ...
> em.persist(itemA);
> ...
> }
>
> saveB()
> {
> em = emf.createEntityManager();
> ...
> em.persist(itemB);
> ...
> }
>
>
> Am I transaction save in both code snippets?
>
> In Hibernate for example I have to use the same session within one transaction and within one thread, so I have to save the session in the threadlocal attribute...
>
>
> Thanks in advance
> Uwe
>