Issue with Batch Saving and OptimisticLockException

Hello !
I am trying to save entities in batches for performance optimization using dataManager.save(saveContext). If an error occurs while saving an entity in the batch, I want to skip that entity by catching the error and continue saving the rest of the entities (one by one) that have no error.
However, I am encountering an issue with OptimisticLockException even though the entity was not yet persisted (I confirmed this because the entity is not found by ID when debugging).

if (batchCount >= BATCH_SIZE) {
    try {
        saveBatchWithTransaction(saveContext)
        publisher?.publish(generatedCount)
        saveContext = SaveContext().setDiscardSaved(true)
        batchCount = 0
    } catch (e: Exception) {
        val attributeValue = sf.getAttribute(networkShapeImporting.identifier)?.toString()
        saveRemainingEntities(saveContext, entityGenerationLog)  
        publisher?.publish(generatedCount)
        saveContext = SaveContext().setDiscardSaved(true)
        batchCount = 0
    }
}

@Transactional
private fun saveBatchWithTransaction(saveContext: SaveContext) {
    dataManager.save(saveContext)
}

private fun saveRemainingEntities(saveContext: SaveContext, entityGenerationLog: StringBuilder) {
    try {
        saveContext.entitiesToSave.forEach { entity ->
            try {
                dataManager.save(entity)  // Attempt to save each entity individually
            } catch (e: Exception) {
                entityGenerationLog.append("Failed to save entity: ${e.message}\n") 
            }
        }
    } catch (innerException: Exception) {
        entityGenerationLog.append("Error while attempting to save remaining entities: ${innerException.message}\n")
    }
}

How can I save the remaining detached entities, and how can I merge them? Thank you

Hi Aycha,

I see the possible reason why you get OptimisticLockException: in the catch section, you are trying to save the same entities that were saved (at least part of them) before in the try section.

How do you check this? Maybe you are in a different transaction?

Also, the @Transactional annotation on a private method has no sense. It’s handled by Spring only when you call a bean method from outside.

Regards,
Konstantin

Thank you for the clarification, it was helpful!