3

いくつかのオブジェクトを保存するためのループがあります。ループ内でサービスメソッドを呼び出し、例外をキャッチします。サービス保存メソッドには@Transactionalという注釈が付けられ、内部ではsaveOrUpdate呼び出しが休止状態になります。サービスは、ApplicationContextオブジェクトのgetBeanメソッドによって提供されます。ループの前に一度だけ呼び出します。

ループ内で、Oracle制約違反の例外をキャッチした後:

org.hibernate.exception.constraintviolationexception:ora-00001:一意の制約(ccb.sys_c0017085)に違反しました

問題をログに記録し、別のオブジェクトを保存しようとしました。私が得る次の例外は次のとおりです。

org.hibernate.HibernateException:プロキシハンドルは無効になりました

各oraエラーの後に1回だけ発生する場合もありますが、さらに多くのオブジェクト(反復)に対して繰り返される場合もあります。

この例外を処理する方法と保存操作を可能にする方法は?

Spring3.1.3とHibernate4.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でのみ発生することです。

4

4 に答える 4

10

私はあなたの問題に関してさまざまな提案があります。

提案1:すべてのトランザクションで同じセッションを誤って再利用しています。

これを確認するには:ブレークポイントを設定し、2回の連続呼び出しでsaveRecordへの参照SessionImplが異なることを確認します。

正直なところ、コードがMS SQL Serverで実行されているため、これが問題になる可能性はほとんどありません。したがって、この提案が正しい唯一のチャンスは、MSSQLServerの制約がOracleの制約と同じではないということです。さらに、この場合、休止状態はより明示的な例外をスローすると思います。

提案2:休止状態4でバグが発生しています

この領域の休止状態のJIRAにはいくつかのバグレポートがあります。(あなたのコードがなければ、あなたの正確な状況を言うのは難しいです)。あなたが持っている振る舞いがそれらのバグの1つに関連している可能性が高いです:

https://hibernate.onjira.com/browse/HHH-7688(これはあなたのものに非常に近いですが、他にもいくつかあります)

このバグの回避策はありますか?

私は試すべきいくつかの提案があります:

hibernate.jdbc.batch_sizeを1より大きい値に設定します。この回避策は、ここでMichale Wyrazによって提案され、機能しているようです。

リフレクションを使用しないでください。役立つかどうかはわかりませんが、トランザクションはaop-proxyによって処理されます。リフレクションを使用すると、トランザクションマネージャーコードの一部がバイパスされる可能性があります(使用しないでください。ただし、確認するための仮説です)。

接続解放モードを変更する:(休止状態のJIRAの)これらすべてのバグは多かれ少なかれJdbcConnection管理に関連しているため、接続解放モードを変更すると、ある時点で問題を特定するのに役立つ場合があります。(Hibernateで実際にバグが発生している場合は、それを変更することが解決策であるとは言いません。おそらく、修正を待つ/貢献するのが最善の選択です)

hibernate 3.Xへのダウングレード:これも解決策とは言えませんが、hibernate4のバグに実際に直面していることを示している可能性があります。

hibernate 4.2以降へのアップグレード:他の回答で示唆されているように、およびhibernateベースコードの最近の変更に関して:hibernateをアップグレードするだけで問題が解決する場合があります。

于 2013-02-10T10:46:28.010 に答える
3

セッションを閉じようとしたときに同様の問題で時間を失いましたが、残念ながら ben75 の提案はどれも機能しませんでした。これは私の環境でした:

  • エラーメッセージ:org.hibernate.HibernateException: proxy handle is no longer valid ...
  • 休止状態バージョン4.1.7
  • アプリケーション サーバー: IBM WebSphere 7

したがって、他の誰かがこのエラーに遭遇した場合に備えて、私にとってうまくいった解決策は Hibernate 4.2 にアップグレードすることでした。必要な 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。

于 2013-03-27T14:45:41.927 に答える
0

推測です。@Transactionalロールバックによる例外でトランザクションを閉じます。そのため、オブジェクトは一種の分離になります。

@Transactional保存するオブジェクトを反復処理するメイン メソッドからを削除し、@Transactional をオブジェクトのみを保存する別のメソッドにします。

于 2013-01-31T09:01:12.687 に答える