2010-03-25 2 views
17

मैं एक ग्लासफ़िश v3 ऐप सर्वर पर ईजेबी और जेपीए के साथ काम कर रहा हूं। मेरे पास एक एंटिटी क्लास है जहां मैं @ कॉलम एनोटेशन के साथ अद्वितीय होने के लिए फ़ील्ड में से एक को मजबूर कर रहा हूं।ईजेबी/जेपीए पर्यावरण में स्पष्ट रूप से बाधा उल्लंघन का संचालन?

@Entity 
public class MyEntity implements Serializable { 

    private String uniqueName; 

    public MyEntity() { 
    } 

    @Column(unique = true, nullable = false) 
    public String getUniqueName() { 
     return uniqueName; 
    } 

    public void setUniqueName(String uniqueName) { 
     this.uniqueName = uniqueName; 
    } 
} 

जब मैं (उम्मीद के रूप में) इस क्षेत्र को एक गैर-अद्वितीय मूल्य मैं एक अपवाद प्राप्त करने के लिए सेट के साथ एक वस्तु लागू करने के लिए जब लेनदेन EJB कंटेनर द्वारा प्रबंधित करता है की कोशिश करो।

1) अपवाद मैं बेकार है "javax.ejb.EJBException:: लेन-देन निरस्त किया गया"

मैं दो समस्याओं मैं चाहता हल करना है। अगर मैं रिकर्सिवली getCause() पर्याप्त बार कहते हैं, मैं अंत में और अधिक उपयोगी "java.sql.SQLIntegrityConstraintViolationException" तक पहुँचते हैं, लेकिन यह अपवाद EclipseLink कार्यान्वयन का हिस्सा है और मैं वास्तव में आरामदायक यह के अस्तित्व पर भरोसा नहीं कर रहा हूँ।

वहाँ जेपीए के साथ विस्तृत त्रुटि जानकारी पाने के लिए एक बेहतर तरीका है?

2) EJB कंटेनर इस त्रुटि लॉग इन करने भले ही मैं इसे पकड़ने और इसे संभाल पर जोर देता है।

वहाँ एक बेहतर तरीका यह त्रुटि जो बेकार अपवाद जानकारी के साथ अपने लॉग को अव्यवस्थित से Glassfish बंद हो जाएगा संभालने के लिए है?

धन्यवाद।

उत्तर

22

मुझे जो अपवाद मिलता है वह अनुपयोगी है "javax.ejb.EJBException: लेनदेन निरस्त"। (...)

मैंने अपनी तरफ से एक परीक्षण किया (जीएफवी 3 और एक्लिप्ससेंक के साथ) और मैं इस व्यवहार की पुष्टि करता हूं। पूर्ण स्टैकट्रेस है:

 
javax.ejb.EJBException: Transaction aborted 
    at com.sun.ejb.containers.BaseContainer.completeNewTx(BaseContainer.java:4997) 
    at com.sun.ejb.containers.BaseContainer.postInvokeTx(BaseContainer.java:4756) 
    at com.sun.ejb.containers.BaseContainer.postInvoke(BaseContainer.java:1955) 
    at com.sun.ejb.containers.BaseContainer.postInvoke(BaseContainer.java:1906) 
    at com.sun.ejb.containers.EJBLocalObjectInvocationHandler.invoke(EJBLocalObjectInvocationHandler.java:198) 
    at com.sun.ejb.containers.EJBLocalObjectInvocationHandlerDelegate.invoke(EJBLocalObjectInvocationHandlerDelegate.java:84) 
    at $Proxy218.myBusinessMethod(Unknown Source) 
    at com.stackoverflow.q2522643.__EJB31_Generated__MyEJB__Intf____Bean__.myBusinessMethod(Unknown Source) 
    at com.stackoverflow.q2522643.MyServlet.doGet(MyServlet.java:28) 
    at javax.servlet.http.HttpServlet.service(HttpServlet.java:734) 
    at javax.servlet.http.HttpServlet.service(HttpServlet.java:847) 
    at org.apache.catalina.core.StandardWrapper.service(StandardWrapper.java:1523) 
    at org.apache.catalina.core.StandardWrapperValve.invoke(StandardWrapperValve.java:279) 
    at org.apache.catalina.core.StandardContextValve.invoke(StandardContextValve.java:188) 
    at org.apache.catalina.core.StandardPipeline.invoke(StandardPipeline.java:641) 
    at com.sun.enterprise.web.WebPipeline.invoke(WebPipeline.java:97) 
    at com.sun.enterprise.web.PESessionLockingStandardPipeline.invoke(PESessionLockingStandardPipeline.java:85) 
    at org.apache.catalina.core.StandardHostValve.invoke(StandardHostValve.java:185) 
    at org.apache.catalina.connector.CoyoteAdapter.doService(CoyoteAdapter.java:332) 
    at org.apache.catalina.connector.CoyoteAdapter.service(CoyoteAdapter.java:233) 
    at com.sun.enterprise.v3.services.impl.ContainerMapper.service(ContainerMapper.java:165) 
    at com.sun.grizzly.http.ProcessorTask.invokeAdapter(ProcessorTask.java:791) 
    at com.sun.grizzly.http.ProcessorTask.doProcess(ProcessorTask.java:693) 
    at com.sun.grizzly.http.ProcessorTask.process(ProcessorTask.java:954) 
    at com.sun.grizzly.http.DefaultProtocolFilter.execute(DefaultProtocolFilter.java:170) 
    at com.sun.grizzly.DefaultProtocolChain.executeProtocolFilter(DefaultProtocolChain.java:135) 
    at com.sun.grizzly.DefaultProtocolChain.execute(DefaultProtocolChain.java:102) 
    at com.sun.grizzly.DefaultProtocolChain.execute(DefaultProtocolChain.java:88) 
    at com.sun.grizzly.http.HttpProtocolChain.execute(HttpProtocolChain.java:76) 
    at com.sun.grizzly.ProtocolChainContextTask.doCall(ProtocolChainContextTask.java:53) 
    at com.sun.grizzly.SelectionKeyContextTask.call(SelectionKeyContextTask.java:57) 
    at com.sun.grizzly.ContextTask.run(ContextTask.java:69) 
    at com.sun.grizzly.util.AbstractThreadPool$Worker.doWork(AbstractThreadPool.java:330) 
    at com.sun.grizzly.util.AbstractThreadPool$Worker.run(AbstractThreadPool.java:309) 
    at java.lang.Thread.run(Thread.java:619) 
Caused by: javax.transaction.RollbackException: Transaction marked for rollback. 
    at com.sun.enterprise.transaction.JavaEETransactionImpl.commit(JavaEETransactionImpl.java:450) 
    at com.sun.enterprise.transaction.JavaEETransactionManagerSimplified.commit(JavaEETransactionManagerSimplified.java:837) 
    at com.sun.ejb.containers.BaseContainer.completeNewTx(BaseContainer.java:4991) 
    ... 34 more 
Caused by: Exception [EclipseLink-4002] (Eclipse Persistence Services - 2.0.0.v20091127-r5931): org.eclipse.persistence.exceptions.DatabaseException 
Internal Exception: java.sql.SQLIntegrityConstraintViolationException: The statement was aborted because it would have caused a duplicate key value in a unique or primary key constraint or unique index identified by 'SQL100326111558470' defined on 'MYENTITY'. 
Error Code: -1 
Call: INSERT INTO MYENTITY (ID, NAME) VALUES (?, ?) 
    bind => [2, Duke!] 
Query: InsertObjectQuery([email protected]) 
    at org.eclipse.persistence.exceptions.DatabaseException.sqlException(DatabaseException.java:324) 
    at org.eclipse.persistence.internal.databaseaccess.DatabaseAccessor.executeDirectNoSelect(DatabaseAccessor.java:800) 
    at org.eclipse.persistence.internal.databaseaccess.DatabaseAccessor.executeNoSelect(DatabaseAccessor.java:866) 
    at org.eclipse.persistence.internal.databaseaccess.DatabaseAccessor.basicExecuteCall(DatabaseAccessor.java:586) 
    at org.eclipse.persistence.internal.databaseaccess.DatabaseAccessor.executeCall(DatabaseAccessor.java:529) 
    at org.eclipse.persistence.internal.sessions.AbstractSession.executeCall(AbstractSession.java:914) 
    at org.eclipse.persistence.internal.queries.DatasourceCallQueryMechanism.executeCall(DatasourceCallQueryMechanism.java:205) 
    at org.eclipse.persistence.internal.queries.DatasourceCallQueryMechanism.executeCall(DatasourceCallQueryMechanism.java:191) 
    at org.eclipse.persistence.internal.queries.DatasourceCallQueryMechanism.insertObject(DatasourceCallQueryMechanism.java:334) 
    at org.eclipse.persistence.internal.queries.StatementQueryMechanism.insertObject(StatementQueryMechanism.java:162) 
    at org.eclipse.persistence.internal.queries.StatementQueryMechanism.insertObject(StatementQueryMechanism.java:177) 
    at org.eclipse.persistence.internal.queries.DatabaseQueryMechanism.insertObjectForWrite(DatabaseQueryMechanism.java:461) 
    at org.eclipse.persistence.queries.InsertObjectQuery.executeCommit(InsertObjectQuery.java:80) 
    at org.eclipse.persistence.queries.InsertObjectQuery.executeCommitWithChangeSet(InsertObjectQuery.java:90) 
    at org.eclipse.persistence.internal.queries.DatabaseQueryMechanism.executeWriteWithChangeSet(DatabaseQueryMechanism.java:286) 
    at org.eclipse.persistence.queries.WriteObjectQuery.executeDatabaseQuery(WriteObjectQuery.java:58) 
    at org.eclipse.persistence.queries.DatabaseQuery.execute(DatabaseQuery.java:675) 
    at org.eclipse.persistence.queries.DatabaseQuery.executeInUnitOfWork(DatabaseQuery.java:589) 
    at org.eclipse.persistence.queries.ObjectLevelModifyQuery.executeInUnitOfWorkObjectLevelModifyQuery(ObjectLevelModifyQuery.java:109) 
    at org.eclipse.persistence.queries.ObjectLevelModifyQuery.executeInUnitOfWork(ObjectLevelModifyQuery.java:86) 
    at org.eclipse.persistence.internal.sessions.UnitOfWorkImpl.internalExecuteQuery(UnitOfWorkImpl.java:2863) 
    at org.eclipse.persistence.internal.sessions.AbstractSession.executeQuery(AbstractSession.java:1225) 
    at org.eclipse.persistence.internal.sessions.AbstractSession.executeQuery(AbstractSession.java:1207) 
    at org.eclipse.persistence.internal.sessions.AbstractSession.executeQuery(AbstractSession.java:1167) 
    at org.eclipse.persistence.internal.sessions.CommitManager.commitNewObjectsForClassWithChangeSet(CommitManager.java:197) 
    at org.eclipse.persistence.internal.sessions.CommitManager.commitAllObjectsWithChangeSet(CommitManager.java:103) 
    at org.eclipse.persistence.internal.sessions.AbstractSession.writeAllObjectsWithChangeSet(AbstractSession.java:3260) 
    at org.eclipse.persistence.internal.sessions.UnitOfWorkImpl.commitToDatabase(UnitOfWorkImpl.java:1405) 
    at org.eclipse.persistence.internal.sessions.RepeatableWriteUnitOfWork.commitToDatabase(RepeatableWriteUnitOfWork.java:547) 
    at org.eclipse.persistence.internal.sessions.UnitOfWorkImpl.commitToDatabaseWithChangeSet(UnitOfWorkImpl.java:1510) 
    at org.eclipse.persistence.internal.sessions.UnitOfWorkImpl.issueSQLbeforeCompletion(UnitOfWorkImpl.java:3134) 
    at org.eclipse.persistence.internal.sessions.RepeatableWriteUnitOfWork.issueSQLbeforeCompletion(RepeatableWriteUnitOfWork.java:268) 
    at org.eclipse.persistence.transaction.AbstractSynchronizationListener.beforeCompletion(AbstractSynchronizationListener.java:157) 
    at org.eclipse.persistence.transaction.JTASynchronizationListener.beforeCompletion(JTASynchronizationListener.java:68) 
    at com.sun.enterprise.transaction.JavaEETransactionImpl.commit(JavaEETransactionImpl.java:412) 
    ... 36 more 
Caused by: java.sql.SQLIntegrityConstraintViolationException: The statement was aborted because it would have caused a duplicate key value in a unique or primary key constraint or unique index identified by 'SQL100326111558470' defined on 'MYENTITY'. 
    at org.apache.derby.client.am.SQLExceptionFactory40.getSQLException(Unknown Source) 
    at org.apache.derby.client.am.SqlException.getSQLException(Unknown Source) 
    at org.apache.derby.client.am.PreparedStatement.executeUpdate(Unknown Source) 
    at com.sun.gjc.spi.base.PreparedStatementWrapper.executeUpdate(PreparedStatementWrapper.java:108) 
    at org.eclipse.persistence.internal.databaseaccess.DatabaseAccessor.executeDirectNoSelect(DatabaseAccessor.java:791) 
    ... 69 more 
Caused by: org.apache.derby.client.am.SqlException: The statement was aborted because it would have caused a duplicate key value in a unique or primary key constraint or unique index identified by 'SQL100326111558470' defined on 'MYENTITY'. 
    at org.apache.derby.client.am.Statement.completeExecute(Unknown Source) 
    at org.apache.derby.client.net.NetStatementReply.parseEXCSQLSTTreply(Unknown Source) 
    at org.apache.derby.client.net.NetStatementReply.readExecute(Unknown Source) 
    at org.apache.derby.client.net.StatementReply.readExecute(Unknown Source) 
    at org.apache.derby.client.net.NetPreparedStatement.readExecute_(Unknown Source) 
    at org.apache.derby.client.am.PreparedStatement.readExecute(Unknown Source) 
    at org.apache.derby.client.am.PreparedStatement.flowExecute(Unknown Source) 
    at org.apache.derby.client.am.PreparedStatement.executeUpdateX(Unknown Source) 
    ... 72 more 

हम देख सकते हैं, EclipseLink वास्तव में एक o.e.p.e.DatabaseException जो तब कंटेनर द्वारा पकड़ा जाता है फेंकता है। लेकिन यह WRONG है। EclipseLink को PersistenceException (जेपीए से) या एक उप-वर्ग में फेंक देना चाहिए, लेकिन निश्चित रूप से प्रदाता विशिष्ट अपवाद नहीं है। यह एक बग है और आप इस तरह के रूप में रिपोर्ट करना चाहिए: https://glassfish.dev.java.net/servlets/ProjectIssues (इकाई-हठ उपघटक में)।

और आप बिल्कुल सही हैं, आपको पोर्टेबिलिटी के लिए पकड़ प्रदाता विशिष्ट अपवाद नहीं होना चाहिए। आपको एक जेपीए PersistenceException या उप-वर्ग (और फिर शायद लपेटा SQLException) को पकड़ना चाहिए। EclipseLink बग के कारण आपको इस विशेष मामले में (अस्थायी रूप से) हो सकता है, लेकिन यह एक कामकाज है।

+0

खबरदार @hallidave कि एक 'PersistenceException' लेन-देन संदर्भ अमान्य हो जाएगी और लेनदेन रोलबैक, * यदि आप इसे नहीं पकड़ या कोई फर्क नहीं *। जावाडोक कहते हैं, "नोरसल्ट अपवाद, गैर-अनन्य रिसेल्ट एक्सेप्शन, लॉकटाइम एक्सेप्शन, और क्वेरीटाइमआउट अपवाद के उदाहरणों को छोड़कर पर्सिस्टेंस एक्सेप्शन के सभी उदाहरण रोलबैक के लिए चिह्नित होने के लिए मौजूदा लेनदेन का कारण बनेंगे।" सादा जेडीबीसी के साथ यह एक बड़ा अंतर था कि आप एक अपवाद निगल सकते हैं (आप जो करते हैं उसके आधार पर) और अभी भी प्रतिबद्ध हैं। – ewernli

+0

@ewernli हां, मैं समझता हूं कि लेन-देन वापस ले लिया गया है इससे कोई फर्क नहीं पड़ता - यह वास्तव में केवल स्टैकट्रैक से भरा लॉग है जो मुझे परेशान कर रहा है। आदर्श रूप से, मैं ईजेबी के संदर्भ में अपवाद को पकड़ना चाहता हूं, लेकिन यह तब तक नहीं होता जब तक कंटेनर लेनदेन करता है। मैं सिर्फ लेनदेन के प्रबंधन के बारे में सोच रहा हूं इसलिए मेरा अधिक नियंत्रण है। – hallidave

+0

क्यों बेहतर होगा, अगर ग्रहण लिंक ने 'PersistenceException' फेंक दिया? आपको यह पता लगाने का कोई मौका नहीं था कि क्या हुआ (कौन सा क्षेत्र एक अद्वितीय बाधा का उल्लंघन करता है (आप एक इकाई में अधिक अनूठा क्षेत्र हो सकते हैं)) – pihentagy

5

मैं कैसे एक पोर्टेबल रास्ते में अद्वितीय बाधा उल्लंघन का पता लगाने के पता नहीं है, सबसे अच्छा के साथ मैं सिर्फ एक PersistenceException के साथ काम कर रहा है आए हैं। अगर कोई इसका जवाब दे सकता है तो मुझे भी दिलचस्पी होगी।

मैं लॉग मुद्दे के साथ कर सकते हैं।

अपने हठ इकाई के अंदर अपने persistence.xml में निम्नलिखित जोड़ें:

<properties> 
    <property name="eclipselink.logging.level" value="SEVERE"/> 
</properties> 

कि अपवादों में से कुछ से छुटकारा मिल जाएगा। आपको अभी भी स्टैक निशान दिखाई देंगे जहां कंटेनर सीएमटी प्रतिबद्ध समय पर अपवाद देख रहा है।कंटेनर उन्हें देखे जाने से पहले आपको इन्हें निगलना होगा। आप निम्नलिखित कर सकते हैं।

1) दृढ़ता समस्या को इंगित करने के लिए एक एप्लिकेशन विशिष्ट अपवाद बनाएं। मैंने अपना डेटास्टोर अपवाद कहा।

2) कोई इंटरफ़ेस दृश्य बीन का उपयोग न करें। बिज़ इंटरफेस में विधि हस्ताक्षर के फेंकने के खंड में DataStoreException जोड़ें।

3) अपने EJB के लिए निम्न विधि जोड़ें:

@AroundInvoke 
public Object interceptor(InvocationContext ic) throws Exception { 
    Object o = null; 
    try { 
     o = ic.proceed(); 
     if (!sessionContext.getRollbackOnly()) { 
      entityManager.flush(); 
     } 
    } catch (PersistenceException ex) { 
     throw new DataStoreException(ex); 
    } 
    return o; 
} 
संबंधित मुद्दे