为了演示我的问题,我有以下简化代码:
家庭服务:
@Service
class FamilyService(
private val familyRepository: FamilyRepository
private val childService: ChildService
) {
@Transactional(rollbackOn = [Exception::class])
fun createFamily(familyLastName: String, childrenNames: List<String>): Family = runBlocking {
val family = createFamilyEntity(familyLastName)
println("family (in main): ${familyRepository.findByIdOrNull(family.id) ?: "none"}")
val children = childrenNames.map { name ->
async(Dispatchers.Default) {
childService.createChild(family.id, name)
}
}.awaitAll()
family
}
private fun createFamilyEntity(familyLastName: String): Family {
val family = Family(id = UUID.randomUUID(), familyLastName = familyLastName)
return familyRepository.save(family)
}
}
儿童服务:
@Service
class ChildService(
private val childRepository: ChildRepository,
private val familyRepository: FamilyRepository
) {
fun createChild(familyId: UUID, name: String): Child {
println("family (in child): ${familyRepository.findByIdOrNull(familyId) ?: "none"}")
val child = Child(id = UUID.randomUUID(), familyId = familyId, name = name)
return childRepository.save(child)
}
}
当
FamilyController
调用 FamilyService.createFamily
时,它会在控制台中打印如下内容:
family (in main): Family(id=...,familyLastName=...,...)
family (in child): none
family (in child): none
family (in child): none
并且在调用
childService.createChild
时返回错误,表示违反了 child
表的外键约束,因为与提供的 family id 关联的行在 family
表中不存在。但是它存在于println
中的createFamily
中,不知道为什么在不同的协程中调用它时就不存在了。
具体来说,错误如下所示(但具有不同的上下文,而不是家庭和子实体):
2024-04-24 14:41:29.743 ERROR 14984 --- [atcher-worker-3] [v:] [cid:] [huid:] o.h.engine.jdbc.spi.SqlExceptionHelper : ERROR: insert or update on table "data_table_record" violates foreign key constraint "data_table_record_table_id_fkey"
Detail: Key (table_id)=(176dfee6-7525-4741-a466-1acb85861317) is not present in table "data_table".
我怀疑您是否处于完整的协程 Spring 堆栈上,因为您的服务类中的方法没有挂起函数。 @Transactional 不应该与协程一起使用(请参阅https://stackoverflow.com/a/64142241/8129835)。根据 Spring 文档,您应该使用
TransactionalOperator
来处理协程中的事务。