很好地处理数据库约束错误 [英] Handling database constraint errors nicely

查看:240
本文介绍了很好地处理数据库约束错误的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

又一次,它应该是简单的......我的任务是将特定的字段放在我们的应用程序的域对象中,并具有唯一的约束。这本身并不是一个很大的挑战。我只是做了以下几点:


$ b

  public class Location {
// more fields

@Column(unique = true)
@NotNull
private String locationName;

// getters and setters
}

到目前为止好,一切顺利,我在运行一些针对数据库的测试时遇到错误。现在我继续开始实现控制器代码,它应该可以处理域对象的编辑。

然后,所有的地狱都破灭了,因为我从中得到了什么我的hibernate是一些堆栈跟踪,似乎阻止任何理智的处理:

  18 :30:20,173错误[org.jboss.ejb3.invocation](http-localhost-127.0.0.1-8443-2)JBAS014134:组件LocationService上的EJB Invocation方法失败public abstract long company.project.services.IService.update java.lang.Object)throws novatec.crm.DataLayerLockException:javax.ejb.EJBTransactionRolledbackException:事务在org.jboss.as.ejb3.tx.CMTTxInterceptor.handleEndTransactionException(CMTTxInterceptor.java:115)处回滚
[jboss- as-ejb3-7.1.1.Final.jar:7.1.1.Final]
at org.jboss.as.ejb3.tx.CMTTxInterceptor.endTransaction(CMTTxInterceptor.java:95)[jboss-as-ejb3- 7.1.1.Final.jar:7.1.1.Final]
在org.jbo ss.as.ejb3.tx.CMTTxInterceptor.invokeInOurTx(CMTTxInterceptor.java:232)[jboss-as-ejb3-7.1.1.Final.jar:7.1.1.Final]
at org.jboss.as。 ejb3.tx.CMTTxInterceptor.required(CMTTxInterceptor.java:304)[jboss-as-ejb3-7.1.1.Final.jar:7.1.1.Final]
at org.jboss.as.ejb3.tx。 CMTTxInterceptor.processInvocation(CMTTxInterceptor.java:190)[jboss-as-ejb3-7.1.1.Final.jar:7.1.1.Final]
at org.jboss.invocation.InterceptorContext.proceed(InterceptorContext.java: 288)[jboss-invocation-1.1.1.Final.jar:1.1.1.Final]
at org.jboss.as.ejb3.component.interceptors.CurrentInvocationContextInterceptor.processInvocation(CurrentInvocationContextInterceptor.java:41)[jboss -as-ejb3-7.1.1.Final.jar:7.1.1.Final]
at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)[rt.jar:1.6.0_45]
.. 。125 more
原因:javax.transaction.RollbackException:ARJUNA016053:无法提交事务。
at com.arjuna.ats.internal.jta.transaction.arjunacore.TransactionImple.commitAndDisassociate(TransactionImple.java:1177)
at com.arjuna.ats.internal.jta.transaction.arjunacore.BaseTransaction。提交(BaseTransaction.java:117)
at com.arjuna.ats.jbossatx.BaseTransactionManagerDelegate.commit(BaseTransactionManagerDelegate.java:75)
at org.jboss.as.ejb3.tx.CMTTxInterceptor.endTransaction( CMTTxInterceptor.java:92)[jboss-as-ejb3-7.1.1.Final.jar:7.1.1.Final]
... 79 more
导致:javax.persistence.PersistenceException:org .bug.exception.ConstraintViolationException:Eindeutiger索引或Primärschlüsselverletzt:CONSTRAINT_INDEX_9 ON PUBLIC.LOCATION(LOCATIONNAME)
唯一索引或主键违例:CONSTRAINT_INDEX_9 ON PUBLIC.LOCATION(LOCATIONNAME); SQL语句:
更新位置set housenumber = ?, locationName =?,numberSuffix = ?, street =?,town =?,version =?,zipcode =?其中id =?和版本=? [23505-161]
在org.hibernate.ejb.AbstractEntityManagerImpl.convert(AbstractEntityManagerImpl.java:1361)[hibernate-entitymanager-4.0.1.Final.jar:4.0.1.Final]
at org.hibernate.ejb.AbstractEntityManagerImpl.convert(AbstractEntityManagerImpl.java:1289)[hibernate-entitymanager-4.0.1.Final.jar:4.0.1.Final]
at org.hibernate.ejb.AbstractEntityManagerImpl.convert( AbstractEntityManagerImpl.java:1295)[hibernate-entitymanager-4.0.1.Final.jar:4.0.1.Final]
at org.hibernate.ejb.AbstractEntityManagerImpl $ CallbackExceptionMapperImpl.mapManagedFlushFailure(AbstractEntityManagerImpl.java:1481)[hibernate -entitymanager-4.0.1.Final.jar:4.0.1.Final]
at org.hibernate.engine.transaction.synchronization.internal.SynchronizationCallbackCoordinatorImpl.beforeCompletion(SynchronizationCallbackCoordinatorImpl.java:109)[hibernate-core-4.0 .1.Final.jar:4.0.1.Final]
在org.hibernate.engine.transaction.synchronization.internal.RegisteredSynchronization.beforeCom pletion(RegisteredSynchronization.java:53)[hibernate-core-4.0.1.Final.jar:4.0.1.Final]
at com.arjuna.ats.internal.jta.resources.arjunacore.SynchronizationImple.beforeCompletion( SynchronizationImple.java:76)
at com.arjuna.ats.arjuna.coordinator.TwoPhaseCoordinator.beforeCompletion(TwoPhaseCoordinator.java:273)
at com.arjuna.ats.arjuna.coordinator.TwoPhaseCoordinator.end( TwoPhaseCoordinator.java:93)
at com.arjuna.ats.arjuna.AtomicAction.commit(AtomicAction.java:164)
at com.arjuna.ats.internal.jta.transaction.arjunacore.TransactionImple。 commitAndDisassociate(TransactionImple.java:1165)
... 82 more
引起:org.hibernate.exception.ConstraintViolationException:Eindeutiger索引或者Primärschlüsselverletzt:CONSTRAINT_INDEX_9 ON PUBLIC.LOCATION(LOCATIONNAME)
唯一索引或主键违例:CONSTRAINT_INDEX_9 ON PUBLIC.LOCATION(LOCATIONNAME); SQL语句:
更新位置set housenumber = ?, locationName =?,numberSuffix = ?, street =?,town =?,version =?,zipcode =?其中id =?和版本=? [23505-161]
在org.hibernate.exception.internal.SQLStateConversionDelegate.convert(SQLStateConversionDelegate.java:128)[hibernate-core-4.0.1.Final.jar:4.0.1.Final]
在org.hibernate.exception.internal.StandardSQLExceptionConverter.convert(StandardSQLExceptionConverter.java:47)[hibernate-core-4.0.1.Final.jar:4.0.1.Final]
在org.hibernate.engine。 jdbc.spi.SqlExceptionHelper.convert(SqlExceptionHelper.java:125)[hibernate-core-4.0.1.Final.jar:4.0.1.Final]
at org.hibernate.engine.jdbc.spi.SqlExceptionHelper。转换(SqlExceptionHelper.java:110)[hibernate-core-4.0.1.Final.jar:4.0.1.Final]
at org.hibernate.engine.jdbc.internal.proxy.AbstractStatementProxyHandler.continueInvocation(AbstractStatementProxyHandler。 java:129)[hibernate-core-4.0.1.Final.jar:4.0.1.Final]
at org.hibernate.engine.jdbc.internal.proxy.AbstractProxyHandler.invoke(AbstractProxyHandler.java:81) [hibernate-core-4.0.1.Final.jar:4.0.1.Final]
at com.sun.proxy。$ Pro xy79.executeUpdate(Unknown Source)
在org.hibernate.persister.entity.AbstractEntityPersister.update(AbstractEntityPersister.java:3010)[hibernate-core-4.0.1.Final.jar:4.0.1.Final]
在org.hibernate.persister.entity.AbstractEntityPersister.updateOrInsert(AbstractEntityPersister.java:2908)[hibernate-core-4.0.1.Final.jar:4.0.1.Final]
在org.hibernate。 persist.entity.AbstractEntityPersister.update(AbstractEntityPersister.java:3237)[hibernate-core-4.0.1.Final.jar:4.0.1.Final]
at org.hibernate.action.internal.EntityUpdateAction.execute( EntityUpdateAction.java:113)[hibernate-core-4.0.1.Final.jar:4.0.1.Final]
at org.hibernate.engine.spi.ActionQueue.execute(ActionQueue.java:272)[hibernate -core-4.0.1.Final.jar:4.0.1.Final]
在org.hibernate.engine.spi.ActionQueue.executeActions(ActionQueue.java:264)[hibernate-core-4.0.1.Final .jar:4.0.1.Final]
在org.hibernate.engine.spi.ActionQueue.executeActions(ActionQueue.java:187)[hibernate- core-4.0.1.Final.jar:4.0.1.Final]
at org.hibernate.event.internal.AbstractFlushingEventListener.performExecutions(AbstractFlushingEventListener.java:326)[hibernate-core-4.0.1.Final。 jar:4.0.1.Final]
在org.hibernate.event.internal.DefaultFlushEventListener.onFlush(DefaultFlushEventListener.java:52)[hibernate-core-4.0.1.Final.jar:4.0.1.Final]
在org.hibernate.internal.SessionImpl.flush(SessionImpl.java:1081)[hibernate-core-4.0.1.Final.jar:4.0.1.Final]
在org.hibernate.internal .SessionImpl.managedFlush(SessionImpl.java:315)[hibernate-core-4.0.1.Final.jar:4.0.1.Final]
at org.hibernate.engine.transaction.synchronization.internal.SynchronizationCallbackCoordinatorImpl.beforeCompletion (SynchronizationCallbackCoordinatorImpl.java:104)[hibernate-core-4.0.1.Final.jar:4.0.1.Final]
... 88 more
导致:org.h2.jdbc.JdbcSQLException: Eindeutiger Index orPrimärschlüsselverletzt:CONSTRAINT_INDEX_9 ON PUBLIC.LOCATION(LOCATIONNAME )
唯一索引或主键违例:CONSTRAINT_INDEX_9 ON PUBLIC.LOCATION(LOCATIONNAME); SQL语句:
更新位置set housenumber = ?, locationName =?,numberSuffix = ?, street =?,town =?,version =?,zipcode =?其中id =?和版本=? [23505-161]
at org.h2.message.DbException.getJdbcSQLException(DbException.java:329)
at org.h2.message.DbException.get(DbException.java:169)
在org.h2.message.DbException.get(DbException.java:146)
在org.h2.index.BaseIndex.getDuplicateKeyException(BaseIndex.java:81)
在org.h2.index。 PageBtree.find(PageBtree.java:121)
at org.h2.index.PageBtreeLeaf.addRow(PageBtreeLeaf.java:146)
at org.h2.index.PageBtreeLeaf.addRowTry(PageBtreeLeaf.java: 100)
at org.h2.index.PageBtreeIndex.addRow(PageBtreeIndex.java:105)
at org.h2.index.PageBtreeIndex.add(PageBtreeIndex.java:96)
at org .h2.table.RegularTable.addRow(RegularTable.java:121)$ or
at org.h2.table.Table.updateRows(Table.java:439)
at org.h2.command.dml.Update .update(Update.java:128)
在org.h2.command.CommandContainer.update(CommandContainer.java:73)
在org.h2.command.Command.executeUpdate(Command.java:219 )在org.h2.serv处
er.TcpServerThread.process(TcpServerThread.java:302)
在org.h2.server.TcpServerThread.run(TcpServerThread.java:137)
在java.lang.Thread.run(未知源)

at org.h2.engine.SessionRemote.done(SessionRemote.java:538)
at org.h2.command.CommandRemote.executeUpdate(CommandRemote.java:183)
at org.h2.jdbc.JdbcPreparedStatement.executeUpdateInternal(JdbcPreparedStatement.java:143)
at org.h2.jdbc.JdbcPreparedStatement.executeUpdate(JdbcPreparedStatement.java:129)
at org.jboss.jca.adapters。
at sun.reflect.GeneratedMethodAccessor391.invoke(Unknown Source)[:1.6.0_45]
at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java :25)[rt.jar:1.6.0_45]
在java.lang.reflect.Method.invoke(Method.java:597)[rt.jar:1.6.0_45]
在org.hibernate .engine.jdbc.internal.proxy.AbstractStatementProxyHandler.co ntinueInvocation(AbstractStatementProxyHandler.java:122)[hibernate-core-4.0.1.Final.jar:4.0.1.Final]
... 102 more

我不希望与此有任何关系,并且我希望将我的可怜用户从这样的例外中拯救出来撞到他的脸上。所以我虽然:嘿,我应该隐藏这个..我做的是以下内容:

 尝试{
服务。更新(对象);
} catch(EJBTransactionRolledbackException e){
Throwable root = e.getCause();
while(root.getCause()!= null){
root = root.getCause();
}
if(root instanceof java.sql.SQLException){
//重复的位置名称
resources.produceFacesContext()。addMessage(
code,
新的FacesMessage(FacesMessage.SEVERITY_WARN,Fehler:,
Der Standortname muss einmalig sein!));
// german for:Error:,LocationName must be unique
}
}

我认为必须是处理此问题的更好方法。应该没有必要回到这种骇人听闻的解决方法,只是为了发现,究竟是什么打破了,所以你可以通知用户他犯的错误。



当然我可以尝试运行一个Validator的Domain Object,它运行一个防御性的SELECT语句。但是在应用程序逻辑中强制实施数据库约束比感染Exception根本原因更加肮脏。



感觉就像我忽略了一些非常明显的东西。

PS如果我没有发现异常,那么所有的事情都会中断......对ConstraintViolationException没有很好的处理。我想这是因为在那里没有定义 ConstraintViolations ...

解决方案

解析异常始终是一个坏主意。特别是你在这里做什么,因为你认为任何SQL异常都是违反约束的结果,实际上SQLException可能有很多许多事情。



如果你设置了数据库对字段的唯一约束,然后尝试输入两次,这就是你将得到的,明显的解决方案不是在发生错误时尝试捕获错误,而是在插入它之前手动检查它是否存在于数据库中。 / p>

Yet again it was supposed to be simple.... I was tasked with placing a certain field in the domain-objects of our application with a unique constraint. That in itself wasn't much of a challenge. I just did the following:

public class Location {
    // more fields

    @Column(unique = true)
    @NotNull
    private String locationName;

    // getters and setters
}

So far so good, all went well and I got an error on running some tests against the database. Now I went ahead and started to implement Controller code, that was supposed to handle edits of the domain object.

And then all hell broke loose, because what I got back from my hibernate was some stack-trace that simply seems to prevent any sane handling of this:

18:30:20,173 ERROR [org.jboss.ejb3.invocation] (http-localhost-127.0.0.1-8443-2) JBAS014134: EJB Invocation failed on component LocationService for method public abstract long company.project.services.IService.update(java.lang.Object) throws novatec.crm.DataLayerLockException: javax.ejb.EJBTransactionRolledbackException: Transaction rolled back
    at org.jboss.as.ejb3.tx.CMTTxInterceptor.handleEndTransactionException(CMTTxInterceptor.java:115) [jboss-as-ejb3-7.1.1.Final.jar:7.1.1.Final]
    at org.jboss.as.ejb3.tx.CMTTxInterceptor.endTransaction(CMTTxInterceptor.java:95) [jboss-as-ejb3-7.1.1.Final.jar:7.1.1.Final]
    at org.jboss.as.ejb3.tx.CMTTxInterceptor.invokeInOurTx(CMTTxInterceptor.java:232) [jboss-as-ejb3-7.1.1.Final.jar:7.1.1.Final]
    at org.jboss.as.ejb3.tx.CMTTxInterceptor.required(CMTTxInterceptor.java:304) [jboss-as-ejb3-7.1.1.Final.jar:7.1.1.Final]
    at org.jboss.as.ejb3.tx.CMTTxInterceptor.processInvocation(CMTTxInterceptor.java:190) [jboss-as-ejb3-7.1.1.Final.jar:7.1.1.Final]
    at org.jboss.invocation.InterceptorContext.proceed(InterceptorContext.java:288) [jboss-invocation-1.1.1.Final.jar:1.1.1.Final]
    at org.jboss.as.ejb3.component.interceptors.CurrentInvocationContextInterceptor.processInvocation(CurrentInvocationContextInterceptor.java:41) [jboss-as-ejb3-7.1.1.Final.jar:7.1.1.Final]
    at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method) [rt.jar:1.6.0_45]
    ... 125 more
Caused by: javax.transaction.RollbackException: ARJUNA016053: Could not commit transaction.
    at com.arjuna.ats.internal.jta.transaction.arjunacore.TransactionImple.commitAndDisassociate(TransactionImple.java:1177)
    at com.arjuna.ats.internal.jta.transaction.arjunacore.BaseTransaction.commit(BaseTransaction.java:117)
    at com.arjuna.ats.jbossatx.BaseTransactionManagerDelegate.commit(BaseTransactionManagerDelegate.java:75)
    at org.jboss.as.ejb3.tx.CMTTxInterceptor.endTransaction(CMTTxInterceptor.java:92) [jboss-as-ejb3-7.1.1.Final.jar:7.1.1.Final]
... 79 more
Caused by: javax.persistence.PersistenceException: org.hibernate.exception.ConstraintViolationException: Eindeutiger Index oder Primärschlüssel verletzt: "CONSTRAINT_INDEX_9 ON PUBLIC.LOCATION(LOCATIONNAME)"
Unique index or primary key violation: "CONSTRAINT_INDEX_9 ON PUBLIC.LOCATION(LOCATIONNAME)"; SQL statement:
update Location set housenumber=?, locationName=?, numberSuffix=?, street=?, town=?, version=?, zipcode=? where id=? and version=? [23505-161]
    at org.hibernate.ejb.AbstractEntityManagerImpl.convert(AbstractEntityManagerImpl.java:1361) [hibernate-entitymanager-4.0.1.Final.jar:4.0.1.Final]
    at org.hibernate.ejb.AbstractEntityManagerImpl.convert(AbstractEntityManagerImpl.java:1289) [hibernate-entitymanager-4.0.1.Final.jar:4.0.1.Final]
    at org.hibernate.ejb.AbstractEntityManagerImpl.convert(AbstractEntityManagerImpl.java:1295) [hibernate-entitymanager-4.0.1.Final.jar:4.0.1.Final]
    at org.hibernate.ejb.AbstractEntityManagerImpl$CallbackExceptionMapperImpl.mapManagedFlushFailure(AbstractEntityManagerImpl.java:1481) [hibernate-entitymanager-4.0.1.Final.jar:4.0.1.Final]
    at org.hibernate.engine.transaction.synchronization.internal.SynchronizationCallbackCoordinatorImpl.beforeCompletion(SynchronizationCallbackCoordinatorImpl.java:109) [hibernate-core-4.0.1.Final.jar:4.0.1.Final]
    at org.hibernate.engine.transaction.synchronization.internal.RegisteredSynchronization.beforeCompletion(RegisteredSynchronization.java:53) [hibernate-core-4.0.1.Final.jar:4.0.1.Final]
    at com.arjuna.ats.internal.jta.resources.arjunacore.SynchronizationImple.beforeCompletion(SynchronizationImple.java:76)
    at com.arjuna.ats.arjuna.coordinator.TwoPhaseCoordinator.beforeCompletion(TwoPhaseCoordinator.java:273)
    at com.arjuna.ats.arjuna.coordinator.TwoPhaseCoordinator.end(TwoPhaseCoordinator.java:93)
    at com.arjuna.ats.arjuna.AtomicAction.commit(AtomicAction.java:164)
    at com.arjuna.ats.internal.jta.transaction.arjunacore.TransactionImple.commitAndDisassociate(TransactionImple.java:1165)
    ... 82 more
Caused by: org.hibernate.exception.ConstraintViolationException: Eindeutiger Index oder Primärschlüssel verletzt: "CONSTRAINT_INDEX_9 ON PUBLIC.LOCATION(LOCATIONNAME)"
Unique index or primary key violation: "CONSTRAINT_INDEX_9 ON PUBLIC.LOCATION(LOCATIONNAME)"; SQL statement:
update Location set housenumber=?, locationName=?, numberSuffix=?, street=?, town=?, version=?, zipcode=? where id=? and version=? [23505-161]
    at org.hibernate.exception.internal.SQLStateConversionDelegate.convert(SQLStateConversionDelegate.java:128) [hibernate-core-4.0.1.Final.jar:4.0.1.Final]
    at org.hibernate.exception.internal.StandardSQLExceptionConverter.convert(StandardSQLExceptionConverter.java:47) [hibernate-core-4.0.1.Final.jar:4.0.1.Final]
    at org.hibernate.engine.jdbc.spi.SqlExceptionHelper.convert(SqlExceptionHelper.java:125) [hibernate-core-4.0.1.Final.jar:4.0.1.Final]
    at org.hibernate.engine.jdbc.spi.SqlExceptionHelper.convert(SqlExceptionHelper.java:110) [hibernate-core-4.0.1.Final.jar:4.0.1.Final]
    at org.hibernate.engine.jdbc.internal.proxy.AbstractStatementProxyHandler.continueInvocation(AbstractStatementProxyHandler.java:129) [hibernate-core-4.0.1.Final.jar:4.0.1.Final]
    at org.hibernate.engine.jdbc.internal.proxy.AbstractProxyHandler.invoke(AbstractProxyHandler.java:81) [hibernate-core-4.0.1.Final.jar:4.0.1.Final]
    at com.sun.proxy.$Proxy79.executeUpdate(Unknown Source)
    at org.hibernate.persister.entity.AbstractEntityPersister.update(AbstractEntityPersister.java:3010) [hibernate-core-4.0.1.Final.jar:4.0.1.Final]
    at org.hibernate.persister.entity.AbstractEntityPersister.updateOrInsert(AbstractEntityPersister.java:2908) [hibernate-core-4.0.1.Final.jar:4.0.1.Final]
    at org.hibernate.persister.entity.AbstractEntityPersister.update(AbstractEntityPersister.java:3237) [hibernate-core-4.0.1.Final.jar:4.0.1.Final]
    at org.hibernate.action.internal.EntityUpdateAction.execute(EntityUpdateAction.java:113) [hibernate-core-4.0.1.Final.jar:4.0.1.Final]
    at org.hibernate.engine.spi.ActionQueue.execute(ActionQueue.java:272) [hibernate-core-4.0.1.Final.jar:4.0.1.Final]
    at org.hibernate.engine.spi.ActionQueue.executeActions(ActionQueue.java:264) [hibernate-core-4.0.1.Final.jar:4.0.1.Final]
    at org.hibernate.engine.spi.ActionQueue.executeActions(ActionQueue.java:187) [hibernate-core-4.0.1.Final.jar:4.0.1.Final]
    at org.hibernate.event.internal.AbstractFlushingEventListener.performExecutions(AbstractFlushingEventListener.java:326) [hibernate-core-4.0.1.Final.jar:4.0.1.Final]
    at org.hibernate.event.internal.DefaultFlushEventListener.onFlush(DefaultFlushEventListener.java:52) [hibernate-core-4.0.1.Final.jar:4.0.1.Final]
    at org.hibernate.internal.SessionImpl.flush(SessionImpl.java:1081) [hibernate-core-4.0.1.Final.jar:4.0.1.Final]
    at org.hibernate.internal.SessionImpl.managedFlush(SessionImpl.java:315) [hibernate-core-4.0.1.Final.jar:4.0.1.Final]
    at org.hibernate.engine.transaction.synchronization.internal.SynchronizationCallbackCoordinatorImpl.beforeCompletion(SynchronizationCallbackCoordinatorImpl.java:104) [hibernate-core-4.0.1.Final.jar:4.0.1.Final]
    ... 88 more
Caused by: org.h2.jdbc.JdbcSQLException: Eindeutiger Index oder Primärschlüssel verletzt: "CONSTRAINT_INDEX_9 ON PUBLIC.LOCATION(LOCATIONNAME)"
Unique index or primary key violation: "CONSTRAINT_INDEX_9 ON PUBLIC.LOCATION(LOCATIONNAME)"; SQL statement:
update Location set housenumber=?, locationName=?, numberSuffix=?, street=?, town=?, version=?, zipcode=? where id=? and version=? [23505-161]
    at org.h2.message.DbException.getJdbcSQLException(DbException.java:329)
    at org.h2.message.DbException.get(DbException.java:169)
    at org.h2.message.DbException.get(DbException.java:146)
    at org.h2.index.BaseIndex.getDuplicateKeyException(BaseIndex.java:81)
    at org.h2.index.PageBtree.find(PageBtree.java:121)
    at org.h2.index.PageBtreeLeaf.addRow(PageBtreeLeaf.java:146)
    at org.h2.index.PageBtreeLeaf.addRowTry(PageBtreeLeaf.java:100)
    at org.h2.index.PageBtreeIndex.addRow(PageBtreeIndex.java:105)
    at org.h2.index.PageBtreeIndex.add(PageBtreeIndex.java:96)
    at org.h2.table.RegularTable.addRow(RegularTable.java:121)
    at org.h2.table.Table.updateRows(Table.java:439)
    at org.h2.command.dml.Update.update(Update.java:128)
    at org.h2.command.CommandContainer.update(CommandContainer.java:73)
    at org.h2.command.Command.executeUpdate(Command.java:219)
    at org.h2.server.TcpServerThread.process(TcpServerThread.java:302)
    at org.h2.server.TcpServerThread.run(TcpServerThread.java:137)
    at java.lang.Thread.run(Unknown Source)

    at org.h2.engine.SessionRemote.done(SessionRemote.java:538)
    at org.h2.command.CommandRemote.executeUpdate(CommandRemote.java:183)
    at org.h2.jdbc.JdbcPreparedStatement.executeUpdateInternal(JdbcPreparedStatement.java:143)
    at org.h2.jdbc.JdbcPreparedStatement.executeUpdate(JdbcPreparedStatement.java:129)
    at org.jboss.jca.adapters.jdbc.WrappedPreparedStatement.executeUpdate(WrappedPreparedStatement.java:493)
    at sun.reflect.GeneratedMethodAccessor391.invoke(Unknown Source) [:1.6.0_45]
    at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:25) [rt.jar:1.6.0_45]
    at java.lang.reflect.Method.invoke(Method.java:597) [rt.jar:1.6.0_45]
    at org.hibernate.engine.jdbc.internal.proxy.AbstractStatementProxyHandler.continueInvocation(AbstractStatementProxyHandler.java:122) [hibernate-core-4.0.1.Final.jar:4.0.1.Final]
    ... 102 more

I don't want anything to do with that, and I want to save my poor user from such an exception which he can't ever be expected to handle when it crashes into his face. So I though: Hey I should hide this.. what I did was the following:

try {
    service.update(object);
} catch (EJBTransactionRolledbackException e) {
    Throwable root = e.getCause();
    while (root.getCause() != null) {
        root = root.getCause();
    }
    if (root instanceof java.sql.SQLException) {
        // duplicate location-name
        resources.produceFacesContext().addMessage(
            "code",
            new FacesMessage(FacesMessage.SEVERITY_WARN, "Fehler:",
                    "Der Standortname muss einmalig sein!"));
        // german for: "Error:", "LocationName must be unique"
    }
}

I think there must be a better way to handle this. There shouldn't be a necessity to revert to such hackish workarounds, just to find out, what exactly broke so you can inform the user of the mistake he's made.

Of course I could try to run the Domain Object against a Validator, that runs a defensive SELECT-statement. But it feels even more dirty to enforce database constraints in application logic, than traversing the Exception root-causes....

It feels like I am overlooking something terribly obvious.

P.S. If I don't catch the exception everything breaks... there is no nice handling of the ConstraintViolationException. I guess it's because there are no ConstraintViolations defined in there...

解决方案

Parsing exceptions is always a bad idea. Especially what you are doing here because you assume any SQL exception to be a consequence of the constraint violation where in reality an SQLException can be many many things.

If you set a database unique constraint on a field, then try to enter it twice, this is what you will get, the obvious solution is not to try to catch the error when it occurs but to manually check if it exists in the database before inserting it.

这篇关于很好地处理数据库约束错误的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

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