java HibernateException:代理句柄在数据库违规错误后不再有效
声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow
原文地址: http://stackoverflow.com/questions/14621801/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me):
StackOverFlow
HibernateException: proxy handle is no longer valid after database violation error
提问by Saram
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.
我有循环来保存几个对象。在循环中调用服务方法并捕获异常。服务保存方法被注解为@Transactional 并且在内部进行休眠 saveOrUpdate 调用。服务由 ApplicationContext 对象的 getBean 方法提供。我只在循环前调用它一次。
In the loop, after i catch exception of oracle constraint violation :
在循环中,在我捕获违反 oracle 约束的异常之后:
org.hibernate.exception.constraintviolationexception: ora-00001: unique constraint (ccb.sys_c0017085) violated
org.hibernate.exception.constraintviolationexception: ora-00001: 违反了唯一约束 (ccb.sys_c0017085)
I log problem and try to save another object. Next exception i get is:
我记录问题并尝试保存另一个对象。我得到的下一个例外是:
org.hibernate.HibernateException: proxy handle is no longer valid
org.hibernate.HibernateException: 代理句柄不再有效
Sometimes it occurs only one time after each ora error but sometimes it repeats for more objects (iterations).
有时它在每个 ora 错误后只发生一次,但有时它会重复更多的对象(迭代)。
How to handle this exception & how to make save operation possible?
如何处理此异常以及如何使保存操作成为可能?
I'm using Spring 3.1.3 and Hibernate 4.1.7.
我使用的是 Spring 3.1.3 和 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
[编辑] 我注意到的最后一件事是它不会发生在 MS SQL Server 上,只发生在 Oracle 上
回答by ben75
I have different suggestions regarding your issue.
我对你的问题有不同的建议。
Suggestion 1: you are wrongly reusing the same session in all transactions.
建议 1:您错误地在所有事务中重用同一个会话。
To check this : put a breakpoint in saveRecord
and check that the reference to the SessionImpl
is different in 2 successive calls.
要检查这一点:在 2 个连续调用中放置一个断点saveRecord
并检查对 的引用SessionImpl
是否不同。
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.
老实说,这是您的问题的可能性很小,因为您的代码是在 MS SQL Server 上运行的。因此,此建议正确的唯一机会是 MS SQL Server 中的约束与 Oracle 中的约束不同。此外,我认为在这种情况下,hibernate 会抛出一个更明确的异常。
Suggestion 2: you are hitting a bug in hibernate 4
建议 2:您在 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:
在这方面,hibernate JIRA 中有一些错误报告。(没有您的代码,很难说出您的确切情况)。您的行为很有可能与这些错误之一有关:
https://hibernate.onjira.com/browse/HHH-7688(this one is very close to yours, but there some others)
https://hibernate.onjira.com/browse/HHH-7688(这个和你的非常接近,但还有其他一些)
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 hereby Michale Wyraz and seems to work.
将 hibernate.jdbc.batch_size 设置为高于 1 的值。此解决方法是由 Michale Wyraz在此处建议的,并且似乎有效。
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).
不要使用反射:不确定它会有所帮助,但事务是由 aop-proxy 处理的,并且使用反射可能会导致绕过一些事务管理器代码(它不应该,但这是一个需要检查的假设)。
Change the connection release mode: all those bugs (in hibernate JIRA) are more or lessrelated to JdbcConnection management, so changing the connection release modemay 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)
更改连接释放模式:所有这些错误(在休眠 JIRA 中)或多或少都与 JdbcConnection 管理有关,因此更改连接释放模式可能会在某些时候帮助您识别问题。(我并不是说改变它是解决方案,如果你真的在休眠中遇到错误:你最好的选择可能是等待/贡献修复)
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.
降级到 hibernate 3.X:我再一次不是说这是一个解决方案,但它可能表明您确实面临 hibernate 4 中的错误。
Upgrading to hibernate 4.2+: As suggested in other answer and regarding recentchanges in hibernate base code: simply upgrading hibernate may solve the problem.
升级到 hibernate 4.2+:正如其他答案中所建议的以及关于hibernate 基本代码的最新变化:简单地升级 hibernate 可能会解决问题。
回答by Miljen Mikic
I lost hours with similar problem when trying to close Session and unfortunately none of ben75's suggestions worked. This was my environment:
尝试关闭 Session 时,我因类似问题而损失了几个小时,不幸的是,ben75 的建议都没有奏效。这是我的环境:
- error message:
org.hibernate.HibernateException: proxy handle is no longer valid ...
- Hibernate version 4.1.7
- application server: IBM WebSphere 7
- 错误信息:
org.hibernate.HibernateException: proxy handle is no longer valid ...
- 休眠版本4.1.7
- 应用服务器:IBM WebSphere 7
so just in the case that someone else stumbles upon this error, solution that worked for me was upgrading to Hibernate 4.2. Required jars are:
因此,以防万一其他人偶然发现此错误,对我有用的解决方案是升级到 Hibernate 4.2。所需的罐子是:
- antlr-2.7.7.jar
- dom4j-1.6.1.jar
- hibernate-commons-annotations-4.0.1.Final.jar
- hibernate-core-4.2.0.Final.jar
- hibernate-jpa-2.0-api-1.0.1.Final.jar
- javassist-3.15.0-GA.jar
- jboss-logging-3.1.0.GA.jar
- jboss-transaction-api_1.1_spec-1.0.0.Final.jar
- antlr-2.7.7.jar
- dom4j-1.6.1.jar
- hibernate-commons-annotations-4.0.1.Final.jar
- hibernate-core-4.2.0.Final.jar
- hibernate-jpa-2.0-api-1.0.1.Final.jar
- javassist-3.15.0-GA.jar
- jboss-logging-3.1.0.GA.jar
- jboss-transaction-api_1.1_spec-1.0.0.Final.jar
HTH.
哈。
回答by StanislavL
Just a guess. @Transactional
closes transaction on Exception by rollback. So objects becomes kind of detached.
只是一个猜测。@Transactional
通过回滚关闭异常事务。所以对象变得有点分离。
I would remove the @Transactional
from the main method where you iterate the objects to be saved and make @Transactional a separet method which only saves objects.
我将从@Transactional
迭代要保存的对象的主要方法中删除,并使@Transactional 成为仅保存对象的单独方法。
回答by Pittmann Gy?rgy
Hibernate 4.1.3 does not close batched statements if they threw an exception (in org.hibernate.engine.jdbc.batch.internal.NonBatchingBatch.addToBatch()). You catch the exception, rollback the current transaction, begin a new one and hope that everything is perfect. But if you run a native update script (for instance), after the run, the finally wants to close the statements. And here it comes, the unclosed (now detached because of the rollback) statement throws this exception and your new transaction goes wrong. Luckily before the new exception the statements get cleared, so only the first update gets wrong... I created a handler method which I call on every rollback (this case it gets called after the initial exception), and after the rollback and begin I create a dummy (and fast) update (update [tablename] set [column]=[column] where 1=2) and execute it. It triggers the above error, I catch it, rolling back the transaction once again and create a new, so I exit the method with a good hibernate session and a living transaction. It is an ugly workaround, but I cannot upgrade hibernate version now...
如果批处理语句抛出异常(在 org.hibernate.engine.jdbc.batch.internal.NonBatchingBatch.addToBatch() 中),Hibernate 4.1.3 不会关闭它们。您捕获异常,回滚当前事务,开始一个新事务并希望一切都完美无缺。但是,如果您运行本机更新脚本(例如),则在运行后,最终要关闭语句。来了,未关闭(现在由于回滚而分离)语句抛出此异常并且您的新事务出错。幸运的是,在新异常之前,语句被清除,所以只有第一次更新出错......我创建了一个处理程序方法,我在每次回滚时调用它(这种情况下它在初始异常之后被调用),在回滚并开始之后,我创建了一个虚拟(和快速)更新(update [tablename] set [column]=[column] where 1=2)并执行它。它触发了上面的错误,我抓住了它,再次回滚事务并创建一个新的,所以我退出了具有良好休眠会话和活动事务的方法。这是一个丑陋的解决方法,但我现在无法升级休眠版本......