2012-01-06 8 views
9

Używanie JPA z implementacją EclipseLink.JPA Żadna transakcja nie jest obecnie aktywna

Kod:

try{ 
    if(!em.getTransaction().isActive()) 
     em.getTransaction().begin(); 
    System.out.println(2); 
    em.persist(currentUser); 
    System.out.println(3); 
    if (em.getTransaction().isActive()){ 
     System.out.println("IS ACTIVE"); 
    } else { 
     System.out.println("NO ACTIVE"); 
    } 
    em.getTransaction().commit(); 
    System.out.println(4); 
    } catch (Exception e){ 
    completed = false; 
    em.getTransaction().rollback(); 
    System.out.println("ERROR: " + e.getMessage()); 
} 

Błąd:

INFO: persistOne - Enter 
INFO: 2 
INFO: 3 
INFO: IS ACTIVE 
INFO: [EL Warning]: 2012-01-06 14:45:59.221--UnitOfWork(12492659)--java.lang.IllegalStateException: During synchronization a new object was found through a relationship that was not marked cascade PERSIST: [email protected] 

WARNING: #{accountController.performRegister}: java.lang.IllegalStateException: 
Exception Description: No transaction is currently active 
javax.faces.FacesException: #{accountController.performRegister}: java.lang.IllegalStateException: 
Exception Description: No transaction is currently active 
    at com.sun.faces.application.ActionListenerImpl.processAction(ActionListenerImpl.java:118) 
    at javax.faces.component.UICommand.broadcast(UICommand.java:315) 
    at javax.faces.component.UIViewRoot.broadcastEvents(UIViewRoot.java:794) 
    at javax.faces.component.UIViewRoot.processApplication(UIViewRoot.java:1259) 
    at com.sun.faces.lifecycle.InvokeApplicationPhase.execute(InvokeApplicationPhase.java:81) 
    at com.sun.faces.lifecycle.Phase.doPhase(Phase.java:101) 
    at com.sun.faces.lifecycle.LifecycleImpl.execute(LifecycleImpl.java:118) 
    at javax.faces.webapp.FacesServlet.service(FacesServlet.java:593) 
    at org.apache.catalina.core.StandardWrapper.service(StandardWrapper.java:1539) 
    at org.apache.catalina.core.StandardWrapperValve.invoke(StandardWrapperValve.java:281) 
    at org.apache.catalina.core.StandardContextValve.invoke(StandardContextValve.java:175) 
    at org.apache.catalina.core.StandardPipeline.doInvoke(StandardPipeline.java:655) 
    at org.apache.catalina.core.StandardPipeline.invoke(StandardPipeline.java:595) 
    at com.sun.enterprise.web.WebPipeline.invoke(WebPipeline.java:98) 
    at com.sun.enterprise.web.PESessionLockingStandardPipeline.invoke(PESessionLockingStandardPipeline.java:91) 
    at org.apache.catalina.core.StandardHostValve.invoke(StandardHostValve.java:162) 
    at org.apache.catalina.connector.CoyoteAdapter.doService(CoyoteAdapter.java:330) 
    at org.apache.catalina.connector.CoyoteAdapter.service(CoyoteAdapter.java:231) 
    at com.sun.enterprise.v3.services.impl.ContainerMapper.service(ContainerMapper.java:174) 
    at com.sun.grizzly.http.ProcessorTask.invokeAdapter(ProcessorTask.java:828) 
    at com.sun.grizzly.http.ProcessorTask.doProcess(ProcessorTask.java:725) 
    at com.sun.grizzly.http.ProcessorTask.process(ProcessorTask.java:1019) 
    at com.sun.grizzly.http.DefaultProtocolFilter.execute(DefaultProtocolFilter.java:225) 
    at com.sun.grizzly.DefaultProtocolChain.executeProtocolFilter(DefaultProtocolChain.java:137) 
    at com.sun.grizzly.DefaultProtocolChain.execute(DefaultProtocolChain.java:104) 
    at com.sun.grizzly.DefaultProtocolChain.execute(DefaultProtocolChain.java:90) 
    at com.sun.grizzly.http.HttpProtocolChain.execute(HttpProtocolChain.java:79) 
    at com.sun.grizzly.ProtocolChainContextTask.doCall(ProtocolChainContextTask.java:54) 
    at com.sun.grizzly.SelectionKeyContextTask.call(SelectionKeyContextTask.java:59) 
    at com.sun.grizzly.ContextTask.run(ContextTask.java:71) 
    at com.sun.grizzly.util.AbstractThreadPool$Worker.doWork(AbstractThreadPool.java:532) 
    at com.sun.grizzly.util.AbstractThreadPool$Worker.run(AbstractThreadPool.java:513) 
    at java.lang.Thread.run(Thread.java:662) 
Caused by: javax.faces.el.EvaluationException: java.lang.IllegalStateException: 
Exception Description: No transaction is currently active 
    at javax.faces.component.MethodBindingMethodExpressionAdapter.invoke(MethodBindingMethodExpressionAdapter.java:102) 
    at com.sun.faces.application.ActionListenerImpl.processAction(ActionListenerImpl.java:102) 
    ... 32 more 
Caused by: java.lang.IllegalStateException: 
Exception Description: No transaction is currently active 
    at org.eclipse.persistence.internal.jpa.transaction.EntityTransactionImpl.rollback(EntityTransactionImpl.java:122) 
    at com.maze.service.UserService.persistOne(UserService.java:63) 
    at com.maze.controller.request.AccountController.performRegister(AccountController.java:62) 
    at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method) 
    at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:39) 
    at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:25) 
    at java.lang.reflect.Method.invoke(Method.java:597) 
    at com.sun.el.parser.AstValue.invoke(AstValue.java:234) 
    at com.sun.el.MethodExpressionImpl.invoke(MethodExpressionImpl.java:297) 
    at com.sun.faces.facelets.el.TagMethodExpression.invoke(TagMethodExpression.java:105) 
    at javax.faces.component.MethodBindingMethodExpressionAdapter.invoke(MethodBindingMethodExpressionAdapter.java:88) 
    ... 33 more 

Najdziwniejsze jest to, że transakcja jest aktywna, ale następna rzecz dzieje jest błąd bezczynności.

EDIT EntityManager Singleton: public class EntityManagerSingleton {

private EntityManagerSingleton(){ 
} 

private static class EMSingletonHolder{ 
    private static final EntityManagerFactory emf = Persistence.createEntityManagerFactory("Maze"); 
    private static final EntityManager em = emf.createEntityManager(); 
} 

public static EntityManager getInstance(){ 
    return EMSingletonHolder.em; 
} 

* Pierwsze wystąpienie EM: *

public abstract class AbstractService { 
protected EntityManager em; 

public AbstractService(){ 
    em = EntityManagerSingleton.getInstance(); 
} 
} 

wszystkie inne usługi wydłuża AbstractService

+0

Chciałbym zwrócić uwagę na to - 'Podczas synchronizacji nowy obiekt został znaleziony przez związek, który nie został oznaczonego kaskadowy PERSIST'. – Perception

Odpowiedz

5

Sądząc po dzienniku, używasz GlassFish. Zakładam, że korzystasz również z JTA. Może możesz podać także kod, który uzyskuje instancję EntityManager? Również debugowanie za pomocą instrukcji System.out jest czymś z przeszłości, użyj debuggera, w przeciwnym razie twój kod jest trudny do odczytania. Ponadto twoje wcięcie jest błędne.

Przede wszystkim, jeśli używasz JTA, spójrz na to pytanie:

EJBException when calling entityManager.getTransaction()

cytat z przyjętą odpowiedzi:

It is illegal to obtain a reference to the EntityTransaction instance associated with the EntityManager in a Java EE managed context. From the Java EE API documentation of EntityManager.getTransaction():

Return the resource-level EntityTransaction object. The EntityTransaction instance may be used serially to begin and commit multiple transactions.

Returns: 
    EntityTransaction instance Throws: 
    IllegalStateException - if invoked on a JTA entity manager 

Dlatego jeśli oczekujesz jakiejkolwiek pomocy, ważne jest podanie informacji o kodzie/zastrzyku, za pośrednictwem którego uzyskujesz podmiot zarządzający.

Również ze względu na czytelność kodu nie powinieneś mieć wielu połączeń z em.getTransaction(); należy przypisać swoje pierwsze wezwanie do przedmiotu transakcji i używać go, trochę tak:

//GOOD cause readable 
EntityTransaction tx = em.getTransaction(); 
tx.begin(); 
em.persist(someObject); 
tx.commit(); 

i nie

//BAD cause hard to read 
em.getTransaction().begin(); 
em.persist(someObject); 
em.getTransaction().commit(); //NO! 
+0

Używam resource_local nie JTA – TGM

+0

Ostatni punkt twojego postu wydaje się być nieprawidłowy w kontekście menedżerów zasobów lokalnych. Nie ma powodu, aby nie wywoływać getTransaction wiele razy, aby uzyskać bieżącą transakcję. EntityManager ma jeden wątek i specyfikacja jawnie pokazuje przykład, który robi to w ten sposób. – chromanoid

+0

@ Chromanoid miałem na myśli warunki odczytu kodu. Zastanów się, czy musisz zachować 4 dodatkowe obiekty. Nazwałbym "em.getTransaction(). Persist (someObject)" jeszcze 4 razy? A może wolisz "tx.persist (someObject)"? W pierwszym podejściu każda z linii odczytałaby jako wykonanie 2 akcji: uzyskać transakcję, utrzymać obiekt. W rzeczywistości to, co chcesz powiedzieć, to "utrzymuj obiekt". –

1

Jeśli spojrzeć na ostatni z tych śladów stosu, widzę

at org.eclipse.persistence.internal.jpa.transaction.EntityTransactionImpl.rollback(EntityTransactionImpl.java:122) 

To błąd podczas wycofywania, a nie podczas zatwierdzania. Zastanawiam się, czy jest to związane z ostrzeżeniem o niepersponowanym obiekcie; coś pójdzie nie tak po zakończeniu zatwierdzania, tak że twój framework próbuje wycofać się w momencie, w którym jest już za późno, aby to zrobić. Założę się, że jeśli poprawnie zarejestrowałeś ten obiekt UserDetail, problem zostałby rozwiązany.

8

Należy zauważyć, że ostatni wyjątek jest zgłaszany przez rollback() w bloku catch.

Więc commit() rzuca następujący wyjątek:

java.lang.IllegalStateException: During synchronization a new object was found through a relationship that was not marked cascade PERSIST: [email protected]

Wyjątek ten powoduje niejawny wycofywania, tak że instrukcja rollback() w bloku catch rzuca inny wyjątek z powodu nieczynnego transakcji.

Aby zapewnić niezawodne czyszczenie ręczne, należy sprawdzić, czy transakcja jest aktywna przed wywołaniem rollback() w bloku catch.

3

Cóż, twoje logi wyjaśniają, podczas zatwierdzania, Eclipselink dostał wyjątek i wycofał transakcję. Dlatego Twój transation nie jest dłużej ..

INFO: [EL Warning]: 2012-01-06 14:45:59.221--UnitOfWork(12492659)--java.lang.IllegalStateException: During synchronization a new object was found through a relationship that was not marked cascade PERSIST: [email protected]

Powiązane problemy