【问题标题】:JPA: deleteAll entries and then recreate single entries in one transactionJPA:删除所有条目,然后在一个事务中重新创建单个条目
【发布时间】:2017-04-24 14:48:11
【问题描述】:

我有一个问题,我想从一个表中删除所有条目,然后从头开始重新创建具有与已删除条目相同 ID 的单个条目。这应该在一个事务中,以便表永远不会为空。

提示:我使用 Spring Batch 并通过块侦听器 beforeChunk(在事务内部)删除 talbe,读取器/写入器随后运行以保存新版本的数据。

目前,如果我这样做,我会收到此错误:

Encountered an error executing step importXXXXX in job jobXXXX java.lang.IllegalArgumentException: Cannot merge an Entity that has been removed

堆栈跟踪:

at org.eclipse.persistence.internal.sessions.MergeManager.registerObjectForMergeCloneIntoWorkingCopy(MergeManager.java:1070) ~[eclipselink-2.6.4.jar:2.6.4.v20160829-44060b6]
at org.eclipse.persistence.internal.sessions.MergeManager.mergeChangesOfCloneIntoWorkingCopy(MergeManager.java:564) ~[eclipselink-2.6.4.jar:2.6.4.v20160829-44060b6]
at org.eclipse.persistence.internal.sessions.MergeManager.mergeChanges(MergeManager.java:313) ~[eclipselink-2.6.4.jar:2.6.4.v20160829-44060b6]
at org.eclipse.persistence.internal.sessions.UnitOfWorkImpl.mergeCloneWithReferences(UnitOfWorkImpl.java:3521) ~[eclipselink-2.6.4.jar:2.6.4.v20160829-44060b6]
at org.eclipse.persistence.internal.sessions.RepeatableWriteUnitOfWork.mergeCloneWithReferences(RepeatableWriteUnitOfWork.java:387) ~[eclipselink-2.6.4.jar:2.6.4.v20160829-44060b6]
at org.eclipse.persistence.internal.sessions.UnitOfWorkImpl.mergeCloneWithReferences(UnitOfWorkImpl.java:3481) ~[eclipselink-2.6.4.jar:2.6.4.v20160829-44060b6]
at org.eclipse.persistence.internal.jpa.EntityManagerImpl.mergeInternal(EntityManagerImpl.java:553) ~[eclipselink-2.6.4.jar:2.6.4.v20160829-44060b6]
at org.eclipse.persistence.internal.jpa.EntityManagerImpl.merge(EntityManagerImpl.java:530) ~[eclipselink-2.6.4.jar:2.6.4.v20160829-44060b6]
at org.springframework.batch.item.database.JpaItemWriter.doWrite(JpaItemWriter.java:104) ~[spring-batch-infrastructure-3.0.7.RELEASE.jar:3.0.7.RELEASE]
at org.springframework.batch.item.database.JpaItemWriter.write(JpaItemWriter.java:83) ~[spring-batch-infrastructure-3.0.7.RELEASE.jar:3.0.7.RELEASE]
at org.springframework.batch.core.step.item.SimpleChunkProcessor.writeItems(SimpleChunkProcessor.java:175) ~[spring-batch-core-3.0.7.RELEASE.jar:3.0.7.RELEASE]
at org.springframework.batch.core.step.item.SimpleChunkProcessor.doWrite(SimpleChunkProcessor.java:151) ~[spring-batch-core-3.0.7.RELEASE.jar:3.0.7.RELEASE]
at org.springframework.batch.core.step.item.SimpleChunkProcessor.write(SimpleChunkProcessor.java:274) ~[spring-batch-core-3.0.7.RELEASE.jar:3.0.7.RELEASE]
at org.springframework.batch.core.step.item.SimpleChunkProcessor.process(SimpleChunkProcessor.java:199) ~[spring-batch-core-3.0.7.RELEASE.jar:3.0.7.RELEASE]
at org.springframework.batch.core.step.item.ChunkOrientedTasklet.execute(ChunkOrientedTasklet.java:75) ~[spring-batch-core-3.0.7.RELEASE.jar:3.0.7.RELEASE]
at org.springframework.batch.core.step.tasklet.TaskletStep$ChunkTransactionCallback.doInTransaction(TaskletStep.java:406) ~[spring-batch-core-3.0.7.RELEASE.jar:3.0.7.RELEASE]
at org.springframework.batch.core.step.tasklet.TaskletStep$ChunkTransactionCallback.doInTransaction(TaskletStep.java:330) ~[spring-batch-core-3.0.7.RELEASE.jar:3.0.7.RELEASE]
at org.springframework.transaction.support.TransactionTemplate.execute(TransactionTemplate.java:133) ~[spring-tx-4.3.7.RELEASE.jar:4.3.7.RELEASE]
at org.springframework.batch.core.step.tasklet.TaskletStep$2.doInChunkContext(TaskletStep.java:271) ~[spring-batch-core-3.0.7.RELEASE.jar:3.0.7.RELEASE]
at org.springframework.batch.core.scope.context.StepContextRepeatCallback.doInIteration(StepContextRepeatCallback.java:81) ~[spring-batch-core-3.0.7.RELEASE.jar:3.0.7.RELEASE]
at org.springframework.batch.repeat.support.RepeatTemplate.getNextResult(RepeatTemplate.java:374) ~[spring-batch-infrastructure-3.0.7.RELEASE.jar:3.0.7.RELEASE]
at org.springframework.batch.repeat.support.RepeatTemplate.executeInternal(RepeatTemplate.java:215) ~[spring-batch-infrastructure-3.0.7.RELEASE.jar:3.0.7.RELEASE]
at org.springframework.batch.repeat.support.RepeatTemplate.iterate(RepeatTemplate.java:144) ~[spring-batch-infrastructure-3.0.7.RELEASE.jar:3.0.7.RELEASE]
at org.springframework.batch.core.step.tasklet.TaskletStep.doExecute(TaskletStep.java:257) ~[spring-batch-core-3.0.7.RELEASE.jar:3.0.7.RELEASE]
at org.springframework.batch.core.step.AbstractStep.execute(AbstractStep.java:200) [spring-batch-core-3.0.7.RELEASE.jar:3.0.7.RELEASE]
at org.springframework.batch.core.job.SimpleStepHandler.handleStep(SimpleStepHandler.java:148) [spring-batch-core-3.0.7.RELEASE.jar:3.0.7.RELEASE]
at org.springframework.batch.core.job.flow.JobFlowExecutor.executeStep(JobFlowExecutor.java:64) [spring-batch-core-3.0.7.RELEASE.jar:3.0.7.RELEASE]
at org.springframework.batch.core.job.flow.support.state.StepState.handle(StepState.java:67) [spring-batch-core-3.0.7.RELEASE.jar:3.0.7.RELEASE]
at org.springframework.batch.core.job.flow.support.SimpleFlow.resume(SimpleFlow.java:169) [spring-batch-core-3.0.7.RELEASE.jar:3.0.7.RELEASE]
at org.springframework.batch.core.job.flow.support.SimpleFlow.start(SimpleFlow.java:144) [spring-batch-core-3.0.7.RELEASE.jar:3.0.7.RELEASE]
at org.springframework.batch.core.job.flow.FlowJob.doExecute(FlowJob.java:134) [spring-batch-core-3.0.7.RELEASE.jar:3.0.7.RELEASE]
at org.springframework.batch.core.job.AbstractJob.execute(AbstractJob.java:306) [spring-batch-core-3.0.7.RELEASE.jar:3.0.7.RELEASE]
at org.springframework.batch.core.launch.support.SimpleJobLauncher$1.run(SimpleJobLauncher.java:135) [spring-batch-core-3.0.7.RELEASE.jar:3.0.7.RELEASE]
at org.springframework.core.task.SyncTaskExecutor.execute(SyncTaskExecutor.java:50) [spring-core-4.3.7.RELEASE.jar:4.3.7.RELEASE]
at org.springframework.batch.core.launch.support.SimpleJobLauncher.run(SimpleJobLauncher.java:128) [spring-batch-core-3.0.7.RELEASE.jar:3.0.7.RELEASE]

您是否有保留该条目的想法,尽管它已在此事务中删除。

谢谢!

【问题讨论】:

  • 这对我来说似乎不可能使用 JPA。您是否尝试过重用实体并仅删除未重用的实体?这似乎也更有效率,因为您只需要进行更新而不是删除和插入。

标签: java spring jpa transactions


【解决方案1】:

specification3.2.4.1 合并分离实体状态部分中有以下内容:

如果 X 是已移除的实体实例,则合并操作将抛出 IllegalArgumentException(否则事务提交将失败)。

它还在3.2.1 持久化实体实例部分中说

如果 X 是一个被移除的实体,它就会变成托管的。

3.2.3 同步到数据库小节中更进一步:

如果 X 是托管实体,则将其同步到数据库。

[...]

  • 如果 X 是已删除的实体,则将从数据库中删除。没有相关的级联选项。

因此,您尝试使用 JPA 做的事情似乎是不可能的。一种解决方法可能是我的评论中建议的实体重用。

【讨论】:

  • 谢谢,这很有趣。您知道将实例标记为“未删除”的方法吗?
  • @SScholl 抱歉,第一次尝试时我没有从规范中获得所有详细信息。所以现在看来​​是不可能的了。
  • 谢谢@SpaceTrucker
猜你喜欢
  • 1970-01-01
  • 2012-11-23
  • 1970-01-01
  • 1970-01-01
  • 2014-05-15
  • 2018-10-16
  • 1970-01-01
  • 2022-07-26
  • 1970-01-01
相关资源
最近更新 更多