2013-05-24 6 views
6

あるデータベースから別のデータベースにデータをコピーしようとしています。ソースデータベースの行の1つが変更されるまで(以下のスタックトレース)、すべて正常に動作しています。宛先データベースに新しい行を追加すると、期待どおりに動作します。あるデータベースから別のデータベースにデータをコピーするとき、org.hibernate.StaleObjectStateExceptionを解決するにはどうすればいいですか?

私は次のBeanから成る各データベース接続(MySQLとHSQLDB)のためのコンテキストファイルがあります:私の@Service

<bean id="mysqlDataSource" class="org.springframework.jdbc.datasource.DriverManagerDataSource"> 
     <property name="driverClassName" value="${mysql.driver}" /> 
     <property name="url" value="${mysql.url}" /> 
     <property name="username" value="${mysql.username}" /> 
     <property name="password" value="${mysql.password}" /> 
    </bean> 

    <bean id="mysqlTransactionManager" class="org.springframework.orm.jpa.JpaTransactionManager"> 
     <property name="entityManagerFactory" ref="mysqlEntityManagerFactory" /> 
     <property name="dataSource" ref="mysqlDataSource" /> 
    </bean> 

    <bean id="mysqlEntityManagerFactory" class="org.springframework.orm.jpa.LocalContainerEntityManagerFactoryBean"> 
     <property name="dataSource"   ref="mysqlDataSource" /> 
     <property name="jpaVendorAdapter" ref="mysqlVendorAdaptor" /> 
     <property name="packagesToScan"  value="my.packages.to.scan"/> 
    </bean> 

    <bean id="mysqlEntityManager" class="org.springframework.orm.jpa.support.SharedEntityManagerBean"> 
     <property name="entityManagerFactory" ref="mysqlEntityManagerFactory"/> 
    </bean> 

    <bean id="mysqlVendorAdaptor" class="org.springframework.orm.jpa.vendor.HibernateJpaVendorAdapter" > 
     <property name="showSql" value="true" /> 
     <property name="generateDdl" value="true" /> 
     <property name="databasePlatform" value="${mysql.dialect}" /> 
    </bean> 

私は、各データベース接続のためのJpaRepositoryを作成します。

@Autowired 
private EntityManager hsqldbEntityManager; 

@Autowired 
private EntityManager mysqlEntityManager; 

private MyRepository hsqldbDao; 
private MyRepository mysqlDao; 

public void init() { 
    hsqldbDao = new JpaRepositoryFactory(hsqldbEntityManager).getRepository(MyRepository.class); 
    mysqlDao = new JpaRepositoryFactory(mysqlEntityManager).getRepository(MyRepository.class); 
} 

MyRepositoryは非常に簡単です:

public interface MyRepository extends JpaRepository<MyClass, byte[]>{ } 

私はSpring Integrationを使用して2つのサービスメソッドをまとめて配線しています。私は両方のEntityManager sからリストを取り外すと、保存する前に深い同じエラーで、リストのクローンを作成しようとしている

@Transactional("mysqlTransactionManager") 
public List<MyClass> findAll() { 
    List<MyClass> list= mysqlDao.findAll(); 
    return list; 
} 

@Transactional("hsqldbTransactionManager") 
public void persist(List<MyClass> list) { 
    hsqldbDao.save(list); 
    hsqldbDao.flush(); 
} 

次のようにサービスの方法があります。したがって、私はトランザクション/エンティティマネージャを設定した方法と関係があると思います。

助けてください。

スタックトレース:

[task-scheduler-1] ERROR org.springframework.integration.handler.LoggingHandler - org.springframework.integration.MessageHandlingException: javax.persistence.OptimisticLockException 
    at org.springframework.integration.handler.MethodInvokingMessageProcessor.processMessage(MethodInvokingMessageProcessor.java:76) 
    at org.springframework.integration.handler.MethodInvokingMessageHandler.handleMessageInternal(MethodInvokingMessageHandler.java:59) 
    at org.springframework.integration.handler.AbstractMessageHandler.handleMessage(AbstractMessageHandler.java:73) 
    at org.springframework.integration.dispatcher.UnicastingDispatcher.doDispatch(UnicastingDispatcher.java:115) 
    at org.springframework.integration.dispatcher.UnicastingDispatcher.dispatch(UnicastingDispatcher.java:102) 
    at org.springframework.integration.channel.AbstractSubscribableChannel.doSend(AbstractSubscribableChannel.java:77) 
    at org.springframework.integration.channel.AbstractMessageChannel.send(AbstractMessageChannel.java:157) 
    at org.springframework.integration.channel.AbstractMessageChannel.send(AbstractMessageChannel.java:128) 
    at org.springframework.integration.core.MessagingTemplate.doSend(MessagingTemplate.java:288) 
    at org.springframework.integration.core.MessagingTemplate.send(MessagingTemplate.java:149) 
    at org.springframework.integration.endpoint.SourcePollingChannelAdapter.handleMessage(SourcePollingChannelAdapter.java:97) 
    at org.springframework.integration.endpoint.AbstractTransactionSynchronizingPollingEndpoint.doPoll(AbstractTransactionSynchronizingPollingEndpoint.java:82) 
    at org.springframework.integration.endpoint.AbstractPollingEndpoint$1.call(AbstractPollingEndpoint.java:146) 
    at org.springframework.integration.endpoint.AbstractPollingEndpoint$1.call(AbstractPollingEndpoint.java:144) 
    at org.springframework.integration.endpoint.AbstractPollingEndpoint$Poller$1.run(AbstractPollingEndpoint.java:236) 
    at org.springframework.integration.util.ErrorHandlingTaskExecutor$1.run(ErrorHandlingTaskExecutor.java:52) 
    at org.springframework.core.task.SyncTaskExecutor.execute(SyncTaskExecutor.java:48) 
    at org.springframework.integration.util.ErrorHandlingTaskExecutor.execute(ErrorHandlingTaskExecutor.java:49) 
    at org.springframework.integration.endpoint.AbstractPollingEndpoint$Poller.run(AbstractPollingEndpoint.java:231) 
    at org.springframework.scheduling.support.DelegatingErrorHandlingRunnable.run(DelegatingErrorHandlingRunnable.java:53) 
    at org.springframework.scheduling.concurrent.ReschedulingRunnable.run(ReschedulingRunnable.java:81) 
    at java.util.concurrent.Executors$RunnableAdapter.call(Unknown Source) 
    at java.util.concurrent.FutureTask$Sync.innerRun(Unknown Source) 
    at java.util.concurrent.FutureTask.run(Unknown Source) 
    at java.util.concurrent.ScheduledThreadPoolExecutor$ScheduledFutureTask.access$301(Unknown Source) 
    at java.util.concurrent.ScheduledThreadPoolExecutor$ScheduledFutureTask.run(Unknown Source) 
    at java.util.concurrent.ThreadPoolExecutor$Worker.runTask(Unknown Source) 
    at java.util.concurrent.ThreadPoolExecutor$Worker.run(Unknown Source) 
    at java.lang.Thread.run(Unknown Source) 
Caused by: javax.persistence.OptimisticLockException 
    at org.hibernate.ejb.AbstractEntityManagerImpl.wrapStaleStateException(AbstractEntityManagerImpl.java:1241) 
    at org.hibernate.ejb.AbstractEntityManagerImpl.convert(AbstractEntityManagerImpl.java:1167) 
    at org.hibernate.ejb.AbstractEntityManagerImpl.convert(AbstractEntityManagerImpl.java:1148) 
    at org.hibernate.ejb.AbstractEntityManagerImpl.convert(AbstractEntityManagerImpl.java:1154) 
    at org.hibernate.ejb.AbstractEntityManagerImpl.merge(AbstractEntityManagerImpl.java:695) 
    at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method) 
    at sun.reflect.NativeMethodAccessorImpl.invoke(Unknown Source) 
    at sun.reflect.DelegatingMethodAccessorImpl.invoke(Unknown Source) 
    at java.lang.reflect.Method.invoke(Unknown Source) 
    at org.springframework.orm.jpa.SharedEntityManagerCreator$SharedEntityManagerInvocationHandler.invoke(SharedEntityManagerCreator.java:240) 
    at $Proxy21.merge(Unknown Source) 
    at org.springframework.data.jpa.repository.support.SimpleJpaRepository.save(SimpleJpaRepository.java:353) 
    at org.springframework.data.jpa.repository.support.SimpleJpaRepository.save(SimpleJpaRepository.java:384) 
    at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method) 
    at sun.reflect.NativeMethodAccessorImpl.invoke(Unknown Source) 
    at sun.reflect.DelegatingMethodAccessorImpl.invoke(Unknown Source) 
    at java.lang.reflect.Method.invoke(Unknown Source) 
    at org.springframework.data.repository.core.support.RepositoryFactorySupport$QueryExecutorMethodInterceptor.executeMethodOn(RepositoryFactorySupport.java:333) 
    at org.springframework.data.repository.core.support.RepositoryFactorySupport$QueryExecutorMethodInterceptor.invoke(RepositoryFactorySupport.java:318) 
    at org.springframework.aop.framework.ReflectiveMethodInvocation.proceed(ReflectiveMethodInvocation.java:172) 
    at org.springframework.data.jpa.repository.support.LockModeRepositoryPostProcessor$LockModePopulatingMethodIntercceptor.invoke(LockModeRepositoryPostProcessor.java:92) 
    at org.springframework.aop.framework.ReflectiveMethodInvocation.proceed(ReflectiveMethodInvocation.java:172) 
    at org.springframework.aop.interceptor.ExposeInvocationInterceptor.invoke(ExposeInvocationInterceptor.java:90) 
    at org.springframework.aop.framework.ReflectiveMethodInvocation.proceed(ReflectiveMethodInvocation.java:172) 
    at org.springframework.aop.framework.JdkDynamicAopProxy.invoke(JdkDynamicAopProxy.java:202) 
    at $Proxy22.save(Unknown Source) 
    at my.package.MyService.persist(xxxxx) 
    at my.package.MyService$$FastClassByCGLIB$$c484c23b.invoke(<generated>) 
    at net.sf.cglib.proxy.MethodProxy.invoke(MethodProxy.java:191) 
    at org.springframework.aop.framework.Cglib2AopProxy$CglibMethodInvocation.invokeJoinpoint(Cglib2AopProxy.java:689) 
    at org.springframework.aop.framework.ReflectiveMethodInvocation.proceed(ReflectiveMethodInvocation.java:150) 
    at org.springframework.transaction.interceptor.TransactionInterceptor.invoke(TransactionInterceptor.java:110) 
    at org.springframework.aop.framework.ReflectiveMethodInvocation.proceed(ReflectiveMethodInvocation.java:172) 
    at org.springframework.aop.framework.Cglib2AopProxy$DynamicAdvisedInterceptor.intercept(Cglib2AopProxy.java:622) 
    at my.package.MyService$$EnhancerByCGLIB$$ed6874cf.persist(<generated>) 
    at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method) 
    at sun.reflect.NativeMethodAccessorImpl.invoke(Unknown Source) 
    at sun.reflect.DelegatingMethodAccessorImpl.invoke(Unknown Source) 
    at java.lang.reflect.Method.invoke(Unknown Source) 
    at org.springframework.expression.spel.support.ReflectiveMethodExecutor.execute(ReflectiveMethodExecutor.java:69) 
    at org.springframework.expression.spel.ast.MethodReference.getValueInternal(MethodReference.java:84) 
    at org.springframework.expression.spel.ast.CompoundExpression.getValueInternal(CompoundExpression.java:57) 
    at org.springframework.expression.spel.ast.SpelNodeImpl.getTypedValue(SpelNodeImpl.java:102) 
    at org.springframework.expression.spel.standard.SpelExpression.getValue(SpelExpression.java:102) 
    at org.springframework.integration.util.AbstractExpressionEvaluator.evaluateExpression(AbstractExpressionEvaluator.java:126) 
    at org.springframework.integration.util.MessagingMethodInvokerHelper.processInternal(MessagingMethodInvokerHelper.java:227) 
    at org.springframework.integration.util.MessagingMethodInvokerHelper.process(MessagingMethodInvokerHelper.java:127) 
    at org.springframework.integration.handler.MethodInvokingMessageProcessor.processMessage(MethodInvokingMessageProcessor.java:73) 
    ... 28 more 
Caused by: org.hibernate.StaleObjectStateException: Row was updated or deleted by another transaction (or unsaved-value mapping was incorrect): [model.MyClass#[[email protected]] 
    at org.hibernate.event.def.DefaultMergeEventListener.entityIsDetached(DefaultMergeEventListener.java:485) 
    at org.hibernate.event.def.DefaultMergeEventListener.onMerge(DefaultMergeEventListener.java:255) 
    at org.hibernate.event.def.DefaultMergeEventListener.onMerge(DefaultMergeEventListener.java:84) 
    at org.hibernate.impl.SessionImpl.fireMerge(SessionImpl.java:867) 
    at org.hibernate.impl.SessionImpl.merge(SessionImpl.java:851) 
    at org.hibernate.impl.SessionImpl.merge(SessionImpl.java:855) 
    at org.hibernate.ejb.AbstractEntityManagerImpl.merge(AbstractEntityManagerImpl.java:686) 
    ... 71 more 

答えて

21

あなたは@Version注釈付きフィールドを使用して、あなたのエンティティで構成された楽観的ロックを持っています。オプティミスティック・ロックの原則は、行に格納されたバージョンが、マージされるエンティティに格納されているバージョンと同じ値を持つ場合にのみ、行の更新を許可することです。それ以外の場合は、取得した例外がスローされます。

このチェックをバイパスするには、更新するエンティティからバージョンを取得し、マージ対象の分離エンティティにコピーします(ターゲットエンティティからこのエンティティをロードした場合のように)。エンティティをマージします。

+0

、あなたの答えをありがとう、私は仕事に戻るときにこれを試してみ火曜日まで待機する必要があります。私はこれをどこか別のところで見て、私のモデルをチェックして、 '@ Version' IIRCを見つけられませんでした。私はデータベースからjavaクラスをリバースエンジニアリングするためにHibernateツールを使用しました。何かが見逃されている可能性があります...ありがとうございました – DairyLea

+2

ありがとう、これは問題でした。 「@ Version」という注釈が付けられたフィールドは、実際にはバージョンではなく、リバースエンジニアリングプロセスがアノテーションを追加しました。アノテーションを削除しても問題はありません... – DairyLea

+0

しかし、チェックをバイパスすることは、更新が失われる可能性があるため、悪い考えです。 – Ogen

2

私は似たような状況で立ち往生して、私を助け、私の手順は以下のとおりであった:

  1. が私のエンティティのコラム
  2. から@Versionアノテーションをコメントアウトし、カラムの更新を作成し、最後に更新を追跡するために作成時間。

コード:

public class AuditEntity implements Serializable { 

    private Date created; 

    // @Version 
    private Date updated; 

    public Date getCreated() { 
     return created; 
    } 

    public void setCreated(Date created) { 
     this.created = created; 
    } 

    public Date getUpdated() { 
     return updated; 
    } 

    public void setUpdated(Date updated) { 
     this.updated = updated; 
    } 

    @PrePersist 
    private void onCreate() { 
     setCreated(Date.now()); 
     setUpdated(Date.now()); 
    } 

    @PostUpdate 
    private void onUpdate() { 
     setUpdated(Date.now()); 
    } 
} 
関連する問題