在 EJB/JPA 环境中优雅地处理约束违规? [英] Elegantly handling constraint violations in EJB/JPA environment?

查看:23
本文介绍了在 EJB/JPA 环境中优雅地处理约束违规?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我正在 Glassfish v3 应用服务器上使用 EJB 和 JPA.我有一个实体类,我在其中使用 @Column 注释强制其中一个字段是唯一的.

@Entity公共类 MyEntity 实现了 Serializable {私人字符串uniqueName;公共我的实体(){}@Column(unique = true, nullable = false)公共字符串 getUniqueName() {返回唯一名称;}public void setUniqueName(String uniqueName) {this.uniqueName = uniqueName;}}

当我尝试将此字段设置为非唯一值的对象持久化时,当 EJB 容器管理的事务提交时,我收到异常(如预期).

我有两个问题要解决:

1) 我得到的异常是无用的javax.ejb.EJBException: Transaction aborted".如果我递归调用 getCause() 的次数足够多,我最终会得到更有用的java.sql.SQLIntegrityConstraintViolationException",但是这个异常是 EclipseLink 实现的一部分,我不太愿意依赖它的存在.

有没有更好的方法来使用 JPA 获取详细的错误信息?

2) EJB 容器坚持记录此错误,即使我捕获并处理它.

是否有更好的方法来处理此错误,以防止 Glassfish 用无用的异常信息弄乱我的日志?

谢谢.

解决方案

我得到的异常是无用的javax.ejb.EJBException: Transaction aborted".(...)

我在我这边做了一个测试(使用 GFv3 和 EclipseLink)并且我确认了这个行为.完整的堆栈跟踪是:

<前>javax.ejb.EJBException:事务中止在 com.sun.ejb.containers.BaseContainer.completeNewTx(BaseContainer.java:4997)在 com.sun.ejb.containers.BaseContainer.postInvokeTx(BaseContainer.java:4756)在 com.sun.ejb.containers.BaseContainer.postInvoke(BaseContainer.java:1955)在 com.sun.ejb.containers.BaseContainer.postInvoke(BaseContainer.java:1906)在 com.sun.ejb.containers.EJBLocalObjectInvocationHandler.invoke(EJBLocalObjectInvocationHandler.java:198)在 com.sun.ejb.containers.EJBLocalObjectInvocationHandlerDelegate.invoke(EJBLocalObjectInvocationHandlerDelegate.java:84)在 $Proxy218.myBusinessMethod(来源不明)在 com.stackoverflow.q2522643.__EJB31_Generated__MyEJB__Intf____Bean__.myBusinessMethod(来源不明)在 com.stackoverflow.q2522643.MyServlet.doGet(MyServlet.java:28)在 javax.servlet.http.HttpServlet.service(HttpServlet.java:734)在 javax.servlet.http.HttpServlet.service(HttpServlet.java:847)在 org.apache.catalina.core.StandardWrapper.service(StandardWrapper.java:1523)在 org.apache.catalina.core.StandardWrapperValve.invoke(StandardWrapperValve.java:279)在 org.apache.catalina.core.StandardContextValve.invoke(StandardContextValve.java:188)在 org.apache.catalina.core.StandardPipeline.invoke(StandardPipeline.java:641)在 com.sun.enterprise.web.WebPipeline.invoke(WebPipeline.java:97)在 com.sun.enterprise.web.PESessionLockingStandardPipeline.invoke(PESessionLockingStandardPipeline.java:85)在 org.apache.catalina.core.StandardHostValve.invoke(StandardHostValve.java:185)在 org.apache.catalina.connector.CoyoteAdapter.doService(CoyoteAdapter.java:332)在 org.apache.catalina.connector.CoyoteAdapter.service(CoyoteAdapter.java:233)在 com.sun.enterprise.v3.services.impl.ContainerMapper.service(ContainerMapper.java:165)在 com.sun.grizzly.http.ProcessorTask.invokeAdapter(ProcessorTask.java:791)在 com.sun.grizzly.http.ProcessorTask.doProcess(ProcessorTask.java:693)在 com.sun.grizzly.http.ProcessorTask.process(ProcessorTask.java:954)在 com.sun.grizzly.http.DefaultProtocolFilter.execute(DefaultProtocolFilter.java:170)在 com.sun.grizzly.DefaultProtocolChain.executeProtocolFilter(DefaultProtocolChain.java:135)在 com.sun.grizzly.DefaultProtocolChain.execute(DefaultProtocolChain.java:102)在 com.sun.grizzly.DefaultProtocolChain.execute(DefaultProtocolChain.java:88)在 com.sun.grizzly.http.HttpProtocolChain.execute(HttpProtocolChain.java:76)在 com.sun.grizzly.ProtocolChainContextTask.doCall(ProtocolChainContextTask.java:53)在 com.sun.grizzly.SelectionKeyContextTask.call(SelectionKeyContextTask.java:57)在 com.sun.grizzly.ContextTask.run(ContextTask.java:69)在 com.sun.grizzly.util.AbstractThreadPool$Worker.doWork(AbstractThreadPool.java:330)在 com.sun.grizzly.util.AbstractThreadPool$Worker.run(AbstractThreadPool.java:309)在 java.lang.Thread.run(Thread.java:619)引起:javax.transaction.RollbackException:事务标记为回滚.在 com.sun.enterprise.transaction.JavaEETransactionImpl.commit(JavaEETransactionImpl.java:450)在 com.sun.enterprise.transaction.JavaEETransactionManagerSimplified.commit(JavaEETransactionManagerSimplified.java:837)在 com.sun.ejb.containers.BaseContainer.completeNewTx(BaseContainer.java:4991)... 34个引起:异常 [EclipseLink-4002] (Eclipse Persistence Services - 2.0.0.v20091127-r5931):org.eclipse.persistence.exceptions.DatabaseException内部异常:java.sql.SQLIntegrityConstraintViolationException:语句被中止,因为它会导致在MYENTITY"上定义的SQL100326111558470"标识的唯一或主键约束或唯一索引中出现重复键值.错误代码:-1调用:INSERT INTO MYENTITY (ID, NAME) VALUES (?, ?)绑定 => [2,公爵!]查询:InsertObjectQuery(com.stackoverflow.q2522643.MyEntity@dba6a9)在 org.eclipse.persistence.exceptions.DatabaseException.sqlException(DatabaseException.java:324)在 org.eclipse.persistence.internal.databaseaccess.DatabaseAccessor.executeDirectNoSelect(DatabaseAccessor.java:800)在 org.eclipse.persistence.internal.databaseaccess.DatabaseAccessor.executeNoSelect(DatabaseAccessor.java:866)在 org.eclipse.persistence.internal.databaseaccess.DatabaseAccessor.basicExecuteCall(DatabaseAccessor.java:586)在 org.eclipse.persistence.internal.databaseaccess.DatabaseAccessor.executeCall(DatabaseAccessor.java:529)在 org.eclipse.persistence.internal.sessions.AbstractSession.executeCall(AbstractSession.java:914)在 org.eclipse.persistence.internal.queries.DatasourceCallQueryMechanism.executeCall(DatasourceCallQueryMechanism.java:205)在 org.eclipse.persistence.internal.queries.DatasourceCallQueryMechanism.executeCall(DatasourceCallQueryMechanism.java:191)在 org.eclipse.persistence.internal.queries.DatasourceCallQueryMechanism.insertObject(DatasourceCallQueryMechanism.java:334)在 org.eclipse.persistence.internal.queries.StatementQueryMechanism.insertObject(StatementQueryMechanism.java:162)在 org.eclipse.persistence.internal.queries.StatementQueryMechanism.insertObject(StatementQueryMechanism.java:177)在 org.eclipse.persistence.internal.queries.DatabaseQueryMechanism.insertObjectForWrite(DatabaseQueryMechanism.java:461)在 org.eclipse.persistence.queries.InsertObjectQuery.executeCommit(InsertObjectQuery.java:80)在 org.eclipse.persistence.queries.InsertObjectQuery.executeCommitWithChangeSet(InsertObjectQuery.java:90)在 org.eclipse.persistence.internal.queries.DatabaseQueryMechanism.executeWriteWithChangeSet(DatabaseQueryMechanism.java:286)在 org.eclipse.persistence.queries.WriteObjectQuery.executeDatabaseQuery(WriteObjectQuery.java:58)在 org.eclipse.persistence.queries.DatabaseQuery.execute(DatabaseQuery.java:675)在 org.eclipse.persistence.queries.DatabaseQuery.executeInUnitOfWork(DatabaseQuery.java:589)在 org.eclipse.persistence.queries.ObjectLevelModifyQuery.executeInUnitOfWorkObjectLevelModifyQuery(ObjectLevelModifyQuery.java:109)在 org.eclipse.persistence.queries.ObjectLevelModifyQuery.executeInUnitOfWork(ObjectLevelModifyQuery.java:86)在 org.eclipse.persistence.internal.sessions.UnitOfWorkImpl.internalExecuteQuery(UnitOfWorkImpl.java:2863)在 org.eclipse.persistence.internal.sessions.AbstractSession.executeQuery(AbstractSession.java:1225)在 org.eclipse.persistence.internal.sessions.AbstractSession.executeQuery(AbstractSession.java:1207)在 org.eclipse.persistence.internal.sessions.AbstractSession.executeQuery(AbstractSession.java:1167)在 org.eclipse.persistence.internal.sessions.CommitManager.commitNewObjectsForClassWithChangeSet(CommitManager.java:197)在 org.eclipse.persistence.internal.sessions.CommitManager.commitAllObjectsWithChangeSet(CommitManager.java:103)在 org.eclipse.persistence.internal.sessions.AbstractSession.writeAllObjectsWithChangeSet(AbstractSession.java:3260)在 org.eclipse.persistence.internal.sessions.UnitOfWorkImpl.commitToDatabase(UnitOfWorkImpl.java:1405)在 org.eclipse.persistence.internal.sessions.RepeatableWriteUnitOfWork.commitToDatabase(RepeatableWriteUnitOfWork.java:547)在 org.eclipse.persistence.internal.sessions.UnitOfWorkImpl.commitToDatabaseWithChangeSet(UnitOfWorkImpl.java:1510)在 org.eclipse.persistence.internal.sessions.UnitOfWorkImpl.issueSQLbeforeCompletion(UnitOfWorkImpl.java:3134)在 org.eclipse.persistence.internal.sessions.RepeatableWriteUnitOfWork.issueSQLbeforeCompletion(RepeatableWriteUnitOfWork.java:268)在 org.eclipse.persistence.transaction.AbstractSynchronizationListener.beforeCompletion(AbstractSynchronizationListener.java:157)在 org.eclipse.persistence.transaction.JTASynchronizationListener.beforeCompletion(JTASynchronizationListener.java:68)在 com.sun.enterprise.transaction.JavaEETransactionImpl.commit(JavaEETransactionImpl.java:412)... 36 更多引起:java.sql.SQLIntegrityConstraintViolationException:语句被中止,因为它会导致在'MYENTITY'上定义的'SQL100326111558470'标识的唯一或主键约束或唯一索引中出现重复的键值.在 org.apache.derby.client.am.SQLExceptionFactory40.getSQLException(来源不明)在 org.apache.derby.client.am.SqlException.getSQLException(来源不明)在 org.apache.derby.client.am.PreparedStatement.executeUpdate(来源不明)在 com.sun.gjc.spi.base.PreparedStatementWrapper.executeUpdate(PreparedStatementWrapper.java:108)在 org.eclipse.persistence.internal.databaseaccess.DatabaseAccessor.executeDirectNoSelect(DatabaseAccessor.java:791)... 69 更多引起:org.apache.derby.client.am.SqlException:语句被中止,因为它会导致在'MYENTITY'上定义的'SQL100326111558470'标识的唯一或主键约束或唯一索引中出现重复的键值.在 org.apache.derby.client.am.Statement.completeExecute(来源不明)在 org.apache.derby.client.net.NetStatementReply.parseEXCSQLSTTreply(来源不明)在 org.apache.derby.client.net.NetStatementReply.readExecute(来源不明)在 org.apache.derby.client.net.StatementReply.readExecute(来源不明)在 org.apache.derby.client.net.NetPreparedStatement.readExecute_(来源不明)在 org.apache.derby.client.am.PreparedStatement.readExecute(来源不明)在 org.apache.derby.client.am.PreparedStatement.flowExecute(来源不明)在 org.apache.derby.client.am.PreparedStatement.executeUpdateX(来源不明)... 72 更多

正如我们所见,EclipseLink 实际上抛出了一个 oepeDatabaseException 然后被容器捕获.但这是错误的.EclipseLink 应该抛出一个 PersistenceException (来自 JPA)或一个,如果它的子类但肯定不是提供者特定的异常.这个一个错误,你应该报告它:https://glassfish.dev.java.net/servlets/ProjectIssues(在entity-persistence 子组件中).

您绝对正确,为了可移植性,您应该不要捕获特定于提供商的异常.您应该捕获 JPA PersistenceException 或一个子类(然后可以查看包装的 SQLException).由于 EclipseLink 错误,您可能必须(暂时)在这种特殊情况下这样做,但这是一种解决方法.

I'm working with EJB and JPA on a Glassfish v3 app server. I have an Entity class where I'm forcing one of the fields to be unique with a @Column annotation.

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

When I try to persist an object with this field set to a non-unique value I get an exception (as expected) when the transaction managed by the EJB container commits.

I have two problems I'd like to solve:

1) The exception I get is the unhelpful "javax.ejb.EJBException: Transaction aborted". If I recursively call getCause() enough times, I eventually reach the more useful "java.sql.SQLIntegrityConstraintViolationException", but this exception is part of the EclipseLink implementation and I'm not really comfortable relying on it's existence.

Is there a better way to get detailed error information with JPA?

2) The EJB container insists on logging this error even though I catch it and handle it.

Is there a better way to handle this error which will stop Glassfish from cluttering up my logs with useless exception information?

Thanks.

解决方案

The exception I get is the unhelpful "javax.ejb.EJBException: Transaction aborted". (...)

I did a test on my side (with GFv3 and EclipseLink) and I confirm this behavior. The full stacktrace is :

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(com.stackoverflow.q2522643.MyEntity@dba6a9)
    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

As we can see, EclipseLink actually throws a o.e.p.e.DatabaseException which is then caught by the container. But this is WRONG. EclipseLink should throw a PersistenceException (from JPA) or one if its subclass but certainly not a provider specific exception. This is a bug and you should report it as such: https://glassfish.dev.java.net/servlets/ProjectIssues (in the entity-persistence subcomponent).

And you're absolutely right, you should NOT catch provider specific exceptions for the sake of portability. You should catch a JPA PersistenceException or a subclass (and then maybe look at the wrapped SQLException). You may have to (temporarily) in this particular case because of the EclipseLink bug, but this is a workaround.

这篇关于在 EJB/JPA 环境中优雅地处理约束违规?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆