Spring Boot 嘗試在不呼叫存盤庫中的 save 方法的情況下為物體 personTransaction1 自動提交 manuell 事務中的更改。personTransaction1 中的更改已提交。方法manuellTransaction拋出org.springframework.orm.ObjectOptimisticLockingFailureException。在方法transactionByAnnotation 中具有基于注釋的事務處理的相同代碼按預期作業,并且沒有提交變數 personTransaction1 的更改。spring 嘗試提交的原因是什么?
@SpringBootApplication
@EnableJpaAuditing
class DbOptimiticLockingApplication : CommandLineRunner {
@Autowired
private lateinit var personRepository: PersonRepository
@Autowired
private lateinit var platformTransactionManager: PlatformTransactionManager
override fun run(vararg args: String?) {
executeInNewTransaction {
personRepository.deleteAll()
}
val person = createPerson()
transactionByAnnotation(person.id)
manuellTransaction(person.id)
}
@Transactional
fun createPerson(): Person {
val person = Person()
person.name = "Max"
return personRepository.save(person)
}
@Transactional(Transactional.TxType.REQUIRES_NEW)
fun transactionByAnnotation(id: Long) {
var personTransaction1 = personRepository.findById(id).get()
// don't trigger commit
personTransaction1.name = "Tom"
transaction11ByAnnotation(personTransaction1.id)
transaction12ByAnnotation(personTransaction1.id)
}
@Transactional(Transactional.TxType.REQUIRES_NEW)
fun transaction11ByAnnotation(id: Long) {
businessLogic1(id)
}
@Transactional(Transactional.TxType.REQUIRES_NEW)
fun transaction12ByAnnotation(id: Long) {
businessLogic2(id)
}
fun manuellTransaction(id: Long) {
executeInNewTransaction {
var personTransaction1 = personRepository.findById(id).get()
// trigger commit
personTransaction1.name = "Tom"
manuellTransaction11(personTransaction1.id)
manuellTransaction12(personTransaction1.id)
}
}
fun manuellTransaction11(id: Long) {
executeInNewTransaction {
businessLogic1(id)
}
}
fun manuellTransaction12(id: Long) {
executeInNewTransaction {
businessLogic2(id)
}
}
private fun businessLogic1(id: Long) {
val person = personRepository.findById(id).get()
person.name = "Martin"
personRepository.saveAndFlush(person)
}
private fun businessLogic2(id: Long) {
val person = personRepository.findById(id).get()
person.name = "Joe"
personRepository.saveAndFlush(person)
}
private fun <T> executeInNewTransaction(action: () -> T): T {
val transactionTemplate = TransactionTemplate(platformTransactionManager)
transactionTemplate.propagationBehavior = TransactionDefinition.PROPAGATION_REQUIRES_NEW
return try {
transactionTemplate.execute {
action()
}!!
} catch (e: Exception) {
throw e
}
}
}
@Entity
@EntityListeners
class Person {
@Id
@GeneratedValue
var id: Long = 0L
@Column
var name: String = ""
@Version
var version: Long = 0L
}
interface PersonRepository : JpaRepository<Person, Long>
fun main(args: Array<String>) {
runApplication<DbOptimiticLockingApplication>(*args)
}
uj5u.com熱心網友回復:
spring 嘗試提交的原因是什么?
當從資料庫中讀取物體時,對于 JPA 層來說,它成為一個persistent或稱為managed物體。
物體persistent/managed狀態由 ORM 供應商觀察,對它們所做的任何更改都會自動傳遞到資料庫層。發生這種情況的前提是,物體被視為persistent/managed完成的方法沒有任何錯誤,并且該方法屬于JPA 事務!

對于您描述的以下參考,不,它沒有按預期作業,您觀察到的行為和您期望發生的事情只是巧合。
transactionByAnnotation 按預期作業,沒有對變數 personTransaction1 進行任何更改
@Transactional(Transactional.TxType.REQUIRES_NEW)
fun transactionByAnnotation(id: Long) {
var personTransaction1 = personRepository.findById(id).get()
@Transactional(Transactional.TxType.REQUIRES_NEW)-> 在您在此處提到的這種情況下被完全忽略,因為該方法的呼叫來自 method 的同一實體run,因此根本不考慮注釋。更多資訊在一個舊的 SO 問題中
因此,由于此方法在沒有任何錯誤的情況下完成但不屬于任何JPA 事務,因此對托管物體所做的更改不會自動傳遞到資料庫中。
如果它屬于 JPA 事務并且@Transactinal沒有因為自呼叫而被忽略,那么它會將更改保留在資料庫中。
轉載請註明出處,本文鏈接:https://www.uj5u.com/qukuanlian/407067.html
標籤:
上一篇:如何使用AsyncIOScheduler從另一個函式運行函式?
下一篇:如何修復無法延遲初始化集合
