There are a lot of questions on this topic. I have searched through stack exchange to find a question which is the same as mine, but haven't found any. Please excuse me if this question has already been asked.
My question is: When using Spring transaction management, what happens when a transactional method with SERIALIZABLE isolation calls another transactional method with REQUIRES_NEW propagation?
As far as I understand, serializable isolation means that any transaction will completely lock the table until it is complete. Meanwhile, a REQUIRES_NEW will make a new transaction and suspend the existing one. This means that since the parent method has not yet completed its transaction, the method that it calls will be instantly deadlocked.
Is my understanding here wrong?
To illustrate, I made an example in Kotlin, which runs without errors in spring, even though it shouldn't, according to my understanding:
open class DummyApplication(val database: Database) {
@Transactional(isolation = Isolation.SERIALIZABLE)
open fun doThing() {
val item = Item("1", "accountId1", "reference1")
database.saveItemWithoutTransaction(item)
val item2 = Item("2", "accountId2", "reference2")
// This call should be instantly deadlocked because it tries to start a new transaction.
database.saveItemWithTransaction(item2)
}
}
and the database:
@Repository
class JdbcDatabase(
private val itemRepository: ItemRepository
) : Database {
override fun saveItemWithoutTransaction(item: Item) {
itemRepository.save(item.toItemEntity())
}
@Transactional(propagation = Propagation.REQUIRES_NEW)
override fun saveItemWithTransaction(item: Item) {
itemRepository.save(item.toItemEntity())
}
}
The itemRepository is a Spring JPA repository, if that is relevant.