HibernateException:在数据库违规错误后,代理句柄不再有效 [英] HibernateException: proxy handle is no longer valid after database violation error

查看:526
本文介绍了HibernateException:在数据库违规错误后,代理句柄不再有效的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我有循环来保存几个对象。在循环中调用服务方法并捕获异常。服务保存方法被标注@Transactional并在内部进行休眠saveOrUpdate调用。
服务由ApplicationContext对象的getBean方法提供。



在循环中,在我发现违反oracle约束的例外之后:


org.hibernate.exception.constraintviolationexception:ora-00001:违反唯一约束(ccb.sys_c0017085)

我记录问题并尝试保存另一个对象。我得到的下一个异常是:

lockquote
org.hibernate.HibernateException:代理句柄不再有效
blockquote>

有时它在每个ora错误后只发生一次,但有时会重复更多的对象(迭代)。



处理这个异常&如何使保存操作可能?

我使用
Spring 3.1.3和Hibernate 4.1.7。



$ p
一些代码示例:

  @Service 
public class ServiceForRecord {
@Transactional
公共记录saveRecord(记录记录,字符串用户){
记录obj =记录;
//一些验证&设置内部值
getHibernateTemplate()。saveOrUpdate(obj)
return obj;


$ / code>

在我的循环中我做到了: p>

  //在params中:
serviceClass = ServiceForRecord.class;
entityClass = Record.class;
saveMethod =saveRecord;
//循环准备
service = getApplicationContext()。getBean(serviceClass);
serviceSave = serviceClass.getMethod(saveRecord,Record.class,String.class);
while(condition){
entity = BeanUtils.instantiate(entityClass);
//设置实体
serviceSave.invoke(service,entity,testUser);
//捕获错误
} //结束而



$ p $
堆栈跟踪:

  PreparedStatementProxyHandler(AbstractProxyHandler).errorIfInvalid()行:63 
PreparedStatementProxyHandler(AbstractStatementProxyHandler)。 continueInvocation(Object,Method,Object [])行:100
PreparedStatementProxyHandler(AbstractProxyHandler).invoke(Object,Method,Object [])line:81
$ Proxy100.clearBatch()line:not available
NonBatchingBatch(AbstractBatchImpl).releaseStatements()行:163
NonBatchingBatch(AbstractBatchImpl).execute()行:152
JdbcCoordinatorImpl.getBatch(BatchKey)行:151
SingleTableEntityPersister(AbstractEntityPersister) .insert(Serializable,Object [],boolean [],int,String,Object,SessionImplementor)行:2940
SingleTableEntityPersister(AbstractEntityPersister).insert(Serializable,Object [],Object,SessionImplementor)行:3403
EntityInsertAction.execute()行:88
ActionQueue.execute(可执行)行:362
ActionQueue.executeActions(List)行:354
ActionQueue.executeActions()行:275
DefaultFlushEventListener(AbstractFlushingEventListener).performExecutions(EventSource )line:326
DefaultFlushEventListener.onFlush(FlushEvent)line:52
SessionImpl.flush()line:1210
SessionImpl.managedFlush()line:399
JdbcTransaction.beforeTransactionCommit() :
HibernateTransactionManager(AbstractPlatformTransactionManager).processCommit(DefaultTransactionStatus)行:754
$ b HibernateTransactionManager(AbstractTransactionStatus)行: b)HibernateTransactionManager(AbstractPlatformTransactionManager).commit(TransactionStatus)行:723
TransactionInterceptor(TransactionAspectSupport).commitTransactionAfterReturning(TransactionAspectSupport $ TransactionInfo)行:392
TransactionInterce ($)
ReflectiveMethodInvocation.proceed()行:172
AfterReturningAdviceInterceptor.invoke(MethodInvocation)行:50
ReflectiveMethodInvocation.proceed()行:172
JdkDynamicAopProxy.invoke(Object,Method,Object [])行:202
$ Proxy71.save(Account,String)行:不可用
GeneratedMethodAccessor115.invoke(Object,Object [])行:not available
DelegatingMethodAccessorImpl.invoke(Object,Object [])行:不可用
Method.invoke(Object,Object ...)行:不可用
ImportServiceProvider.save(Object,String)行:380




我注意到的最后一件事是它不会出现在MS上SQL Server,仅限于Oracle

解决方案

关于您的问题,我有不同的建议。



建议1 :您在所有交易中错误地重复使用同一个会话。



这个:在 saveRecord 中放置一个断点,并检查对于 SessionImpl 的引用在两次连续调用中是不同的。 p>

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



建议2 :你在hibernate 4中遇到了一个bug。 p>

hibernate JIRA中有一些bug报告在这个区域。 (没有你的代码,很难说你的确切情况)。您有很好的机会将您的行为与这些错误之一相关联:

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

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



我有几点建议可以尝试:

将hibernate.jdbc.batch_size设置为大于1 的内容。这种解决方法是建议 here here by Michale Wyraz,似乎有用。



不要使用反射:不确定它会有所帮助,但交易是由aop-proxy处理的,使用反射可能会导致绕过一些交易管理器代码(它不应该,但这是一个检查假设)。

更改连接释放模式:所有这些缺陷(在hibernate JIRA中)与JdbcConnection管理相关的或多或少,因此更改连接发布模式可能会在某些时候帮助您找出问题。 (我并不是说改变它就是解决方案,如果你真的打了一个hibernate的bug:你最好的选择可能是等待/有助于修复)

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



升级到hibernate 4.2 + :正如其他答案和关于hibernate基本代码中最近的更改所建议的:简单地升级hibernate可以解决问题。 p>

I have loop to save couple of objects. In loop a call service method and catch exceptions. Service save method is annotated @Transactional and inside does hibernate saveOrUpdate call. Service is provided by getBean method of ApplicationContext object. I call it only once before loop.

In the loop, after i catch exception of oracle constraint violation :

org.hibernate.exception.constraintviolationexception: ora-00001: unique constraint (ccb.sys_c0017085) violated

I log problem and try to save another object. Next exception i get is:

org.hibernate.HibernateException: proxy handle is no longer valid

Sometimes it occurs only one time after each ora error but sometimes it repeats for more objects (iterations).

How to handle this exception & how to make save operation possible?

I'm using Spring 3.1.3 and Hibernate 4.1.7.

[edit] Some code sample:

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

and in my loop i do:

//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

[edit] Stack trace:

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

[edit] last thing i noticed is that it does not occur on MS SQL Server, only on Oracle

解决方案

I have different suggestions regarding your issue.

Suggestion 1 : you are wrongly reusing the same session in all transactions.

To check this : put a breakpoint in saveRecord and check that the reference to the SessionImpl is different in 2 successive calls.

Honestly, there are few chances this is your problem because your code is running with MS SQL Server. So the only chance for this suggestion to be correct is that the constraints in MS SQL Server are not the same as the constraints in Oracle. Additionally, I think hibernate will throw a more explicit exception in this case.

Suggestion 2 : you are hitting a bug in hibernate 4

There are a few bug reports in hibernate JIRA in this area. (without your code, it's difficult to say what's your exact situation). There are good chance the behavior you have is linked to one of those bugs:

https://hibernate.onjira.com/browse/HHH-7688 (this one is very close to yours, but there some others)

Is there some workarounds to this bug ?

I have few suggestions to try :

set hibernate.jdbc.batch_size to something above 1 . This workaround was suggested here by Michale Wyraz and seems to work.

Don't use reflection : not sure it will help, but transaction is handled by aop-proxy, and using reflection may cause to bypass some of the transaction manager code (it shouldn't, but it's an hypothesis to check).

Change the connection release mode : all those bugs (in hibernate JIRA) are more or less related to JdbcConnection management, so changing the connection release mode may at somepoint help you to identify the issue. (I don't say that changing it is the solution, if you are really hitting a bug in hibernate: your best choice is probably to wait/contribute for the fix)

Downgrading to hibernate 3.X : Once again I don't say it's a solution, but it may indicate that you are really facing a bug in hibernate 4.

Upgrading to hibernate 4.2+ : As suggested in other answer and regarding recent changes in hibernate base code: simply upgrading hibernate may solve the problem.

这篇关于HibernateException:在数据库违规错误后,代理句柄不再有效的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

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