HibernateException:数据库违规错误后代理句柄不再有效

Sar*_*ram 3 java spring hibernate

我有循环来保存几个对象.在循环中调用服务方法并捕获异常.服务保存方法注释@Transactional,内部执行hibernate saveOrUpdate调用.服务由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;
    }
...
Run Code Online (Sandbox Code Playgroud)

在我的循环中,我做:

//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
Run Code Online (Sandbox Code Playgroud)

[编辑]堆栈跟踪:

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
Run Code Online (Sandbox Code Playgroud)

[编辑]我注意到的最后一件事是它不会发生在MS SQL Server上,只发生在Oracle上

ben*_*n75 10

我对你的问题有不同的建议.

建议1:您错误地在所有事务中重用相同的会话.

要检查这一点:输入一个断点saveRecord并检查SessionImpl2个连续调用中对它的引用是否不同.

老实说,这是您的问题的可能性很小,因为您的代码与MS SQL Server一起运行.因此,这个建议正确的唯一机会是MS SQL Server中的约束与Oracle中的约束不同.另外,我认为在这种情况下,hibernate会抛出一个更明确的异常.

建议2:你正在遇到hibernate 4中的一个bug

在这个领域的hibernate JIRA中有一些bug报告.(没有你的代码,很难说出你的具体情况).您的行为很可能与其中一个错误相关联:

https://hibernate.onjira.com/browse/HHH-7688(这个非常接近你的,但还有其他一些)

这个bug有一些解决方法吗?

我几乎没有尝试过的建议:

将hibernate.jdbc.batch_size设置为高于1的值.Michale Wyraz 在这里提出这种解决方法,似乎有效.

不要使用反射:不确定它会有用,但是事务由aop-proxy处理,并且使用反射可能会导致绕过一些事务管理器代码(它不应该,但它是一个检查的假设).

更改连接释放模式:所有这些错误(在休眠JIRA中)或多或少与JdbcConnection管理相关,因此更改连接释放模式可能会在某些时候帮助您识别问题.(我不是说改变它是解决方案,如果你真的遇到了hibernate中的一个bug:你最好的选择可能是等待/贡献修复)

降级为休眠3.X:我再一次不说它是一个解决方案,但它可能表明你真的遇到了hibernate 4中的一个bug.

升级到hibernate 4.2+:正如其他答案所建议的那样,关于hibernate基本代码的最新变化:只需升级hibernate就可以解决问题.