我有循环来保存几个对象。循环调用服务方法并捕获异常。服务保存方法带有@Transactional注释,并且在内部进行hibernatesaveOrUpdate调用。服务由ApplicationContext对象的getBean方法提供。我在循环之前只调用一次。
在循环中,在我捕获到oracle约束违反异常之后:
org.hibernate.exception.constraintviolationexception:ORA-00001:违反了唯一约束(ccb.sys_c0017085)
我记录问题并尝试保存另一个对象。我得到的下一个例外是:
org.hibernate.HibernateException:代理句柄不再有效
有时,它仅在每个ora错误之后发生一次,但有时会针对更多对象(迭代)重复。
如何处理此异常以及如何使保存操作成为可能?
我正在使用Spring 3.1.3和Hibernate 4.1.7。
[编辑]一些代码示例:
@Service public class ServiceForRecord { @Transactional public Record saveRecord(Record record, String user) { Record obj = record; // some validation & seting internal values getHibernateTemplate().saveOrUpdate(obj) return obj; } ...
在我的循环中,我这样做:
//in params: serviceClass = ServiceForRecord.class; entityClass = Record.class; saveMethod = "saveRecord"; //loop prepare service = getApplicationContext().getBean(serviceClass); serviceSave = serviceClass.getMethod("saveRecord", Record.class, String.class); while (condition) { entity = BeanUtils.instantiate(entityClass); //setup entity serviceSave.invoke(service, entity, "testUser"); //catch error } //end while
[编辑]堆栈跟踪:
PreparedStatementProxyHandler(AbstractProxyHandler).errorIfInvalid() line: 63 PreparedStatementProxyHandler(AbstractStatementProxyHandler).continueInvocation(Object, Method, Object[]) line: 100 PreparedStatementProxyHandler(AbstractProxyHandler).invoke(Object, Method, Object[]) line: 81 $Proxy100.clearBatch() line: not available NonBatchingBatch(AbstractBatchImpl).releaseStatements() line: 163 NonBatchingBatch(AbstractBatchImpl).execute() line: 152 JdbcCoordinatorImpl.getBatch(BatchKey) line: 151 SingleTableEntityPersister(AbstractEntityPersister).insert(Serializable, Object[], boolean[], int, String, Object, SessionImplementor) line: 2940 SingleTableEntityPersister(AbstractEntityPersister).insert(Serializable, Object[], Object, SessionImplementor) line: 3403 EntityInsertAction.execute() line: 88 ActionQueue.execute(Executable) line: 362 ActionQueue.executeActions(List) line: 354 ActionQueue.executeActions() line: 275 DefaultFlushEventListener(AbstractFlushingEventListener).performExecutions(EventSource) line: 326 DefaultFlushEventListener.onFlush(FlushEvent) line: 52 SessionImpl.flush() line: 1210 SessionImpl.managedFlush() line: 399 JdbcTransaction.beforeTransactionCommit() line: 101 JdbcTransaction(AbstractTransactionImpl).commit() line: 175 HibernateTransactionManager.doCommit(DefaultTransactionStatus) line: 480 HibernateTransactionManager(AbstractPlatformTransactionManager).processCommit(DefaultTransactionStatus) line: 754 HibernateTransactionManager(AbstractPlatformTransactionManager).commit(TransactionStatus) line: 723 TransactionInterceptor(TransactionAspectSupport).commitTransactionAfterReturning(TransactionAspectSupport$TransactionInfo) line: 392 TransactionInterceptor.invoke(MethodInvocation) line: 120 ReflectiveMethodInvocation.proceed() line: 172 AfterReturningAdviceInterceptor.invoke(MethodInvocation) line: 50 ReflectiveMethodInvocation.proceed() line: 172 JdkDynamicAopProxy.invoke(Object, Method, Object[]) line: 202 $Proxy71.save(Account, String) line: not available GeneratedMethodAccessor115.invoke(Object, Object[]) line: not available DelegatingMethodAccessorImpl.invoke(Object, Object[]) line: not available Method.invoke(Object, Object...) line: not available ImportServiceProvider.save(Object, String) line: 380
我注意到的最后一件事是它不会在MS SQL Server上发生,仅在Oracle上会发生
关于您的问题,我有不同的建议。
建议1 :您在所有交易中都错误地重用了同一会话。
要检查此问题,请执行以下操作:放入一个断点,saveRecord并检查SessionImpl2个连续调用中对的引用是否不同。
saveRecord
SessionImpl
老实说,这是您的问题的几率很小,因为您的代码正在与MS SQL Server一起运行。因此,此建议正确的唯一机会是MS SQL Server中的约束与Oracle中的约束不同。另外,我认为在这种情况下,hibernate将抛出更明确的异常。
建议2 :您在hibernate4中遇到错误
hibernateJIRA中有一些有关此区域的错误报告。(没有您的代码,很难说出您的确切情况)。您的行为很有可能与这些错误之一相关:
https://hibernate.onjira.com/browse/HHH-7688(这个位置与您的位置非常接近,但还有其他位置)
这个错误有一些解决方法吗?
我有一些建议可以尝试:
将hibernate.jdbc.batch_size设置为大于1的值 。此解决方法由Michale Wyraz 建议在此处使用,并且似乎有效。
不要使用反射 :不确定它是否会帮助,但是事务是由aop- proxy处理的,并且使用反射可能会导致绕过某些事务管理器代码(不应该这样做,但这是要检查的假设)。
更改连接释放模式 :所有这些bug(在hibernateJIRA中) 或多或少都 与JdbcConnection管理有关,因此更改连接释放模式可能会在某个时候帮助您识别问题。(如果您确实遇到了hibernate中的错误,那么我并不是说更改它是解决方案:您最好的选择可能是等待/提供此修复程序)
降级到hibernate3.X :我再也不说这是一种解决方案,但是它可能表明您确实面临着hibernate4中的错误。
升级到hibernate 4.2+ :如其他答案中所建议的,并且有关hibernate基本代码的 最新 更改:只需升级hibernate即可解决问题。