2012-01-06 41 views
9

Sử dụng JPA với thực thi EclipseLink.JPA Không có giao dịch nào đang hoạt động

Code:

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()); 
} 

Lỗi:

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 

Điều kỳ lạ là các giao dịch đang hoạt động nhưng điều tiếp theo xảy ra là một lỗi không hoạt động.

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; 
} 

* Lấy em Instance: *

public abstract class AbstractService { 
protected EntityManager em; 

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

Tất cả các dịch vụ khác mở rộng AbstractService

+0

Tôi sẽ chú ý đến điều này - 'Trong quá trình đồng bộ hóa một đối tượng mới được tìm thấy thông qua mối quan hệ không được đánh dấu thác PERSIST'. – Perception

Trả lời

5

Đánh giá bằng nhật ký của bạn, bạn đang sử dụng GlassFish. Tôi cho rằng bạn cũng đang sử dụng JTA. Có lẽ bạn cũng có thể cung cấp mã nhận được cá thể EntityManager? Ngoài ra, gỡ lỗi với các câu lệnh System.out là một cái gì đó trong quá khứ, sử dụng một trình gỡ lỗi, nếu không mã của bạn khó đọc. Ngoài ra, thụt đầu dòng của bạn là sai.

Trước hết, nếu bạn đang sử dụng JTA, hãy nhìn vào câu hỏi này:

EJBException when calling entityManager.getTransaction()

Trích từ câu trả lời được chấp nhận:

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 

Đó là lý do tại sao nếu bạn mong đợi bất kỳ sự trợ giúp nào là quan trọng để cung cấp thông tin về mã/tiêm mà qua đó bạn có được trình quản lý thực thể.

Ngoài ra, vì lợi ích của khả năng đọc mã, bạn không nên có nhiều cuộc gọi đến em.getTransaction(); Bạn nên gán gọi đầu tiên của bạn đến một đối tượng giao dịch và tái sử dụng nó, kinda như thế này:

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

và không

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

Tôi đang sử dụng resource_local không phải JTA – TGM

+0

Điểm cuối cùng của bài đăng của bạn có vẻ không đúng trong ngữ cảnh của các nhà quản lý thực thể tài nguyên địa phương. Không có lý do tại sao không gọi getTransaction nhiều lần để có được giao dịch hiện tại. EntityManager là một luồng đơn và spec hiển thị rõ ràng một ví dụ thực hiện theo cách này. – chromanoid

+0

@chromanoid Tôi có nghĩa là điều khoản của khả năng đọc mã. Hãy xem xét bạn cần phải tồn tại thêm 4 đối tượng. Bạn có gọi 'em.getTransaction(). Persist (someObject)' 4 lần nữa không? Hay bạn thích 'tx.persist (someObject)'? Trong cách tiếp cận đầu tiên, mỗi dòng sẽ đọc như thực hiện 2 hành động: nhận giao dịch, tiếp tục tồn tại đối tượng. Trong khi trên thực tế những gì bạn muốn nói là 'kiên trì đối tượng'. –

1

Nếu bạn nhìn vào các cuối cùng của những đống dấu vết, tôi thấy

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

Đó là lỗi trong khi khôi phục, không phải trong quá trình cam kết. Tôi tự hỏi nếu điều này có liên quan đến cảnh báo về đối tượng không được hỗ trợ; một cái gì đó đi sai ở phần cuối của các cam kết như vậy mà khuôn khổ của bạn cố gắng một rollback tại một điểm mà nó là quá muộn để làm như vậy. Tôi đặt cược nếu bạn đăng ký chính xác đối tượng UserDetail, vấn đề sẽ rõ ràng.

8

Lưu ý rằng ngoại lệ cuối cùng được ném bởi rollback() trong khối catch.

Vì vậy, commit() ném ngoại lệ sau đây:

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

ngoại lệ đó gây ra một rollback tiềm ẩn, do đó hướng dẫn rollback() trong khối catch ném ngoại lệ khác do giao dịch không hoạt động.

Để dọn dẹp thủ công đáng tin cậy, bạn cần kiểm tra xem giao dịch có hoạt động hay không trước khi gọi số rollback() trong khối catch.

3

Vâng, nhật ký của bạn giải thích, trong khi cam kết, Eclipselink có ngoại lệ và quay lại giao dịch của bạn. Đó là lý do tại sao quá trình chuyển đổi của bạn không còn hoạt động nữa.

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]

Các vấn đề liên quan