Итак, у меня есть метод, который загружает некоторые тестовые данные в базу данных.
object FooTestData{
var fooID = -1L
internal set
var barID = -1L
internal set
}
fun TestDataInserter.fooTestData(){
fooID = insertNewFooReturningID("foo")
barID = insertNewFooReturningID("bar")
}
}
Теперь я хочу убедиться, что он загружается ровно один раз.
Это кажется достаточно простым ...
object FooTestData{
internal var isLoaded = false
var fooID = -1L
internal set
var barID = -1L
internal set
}
fun TestDataInserter.fooTestData(){
if(FooTestData.isLoaded) return
FooTestData.isLoaded = true
with(FooTestData){
fooID = insertNewFooReturningID("foo")
barID = insertNewFooReturningID("bar")
}
}
НО что если транзакция - если есть транзакция - в которой это происходит, откатывается?
Тогда у нас нет сущностей в базе данных, недопустимых идентификаторов в объекте FooTestData
и установленного флага isLoaded
, который не позволяет нам когда-либо снова загружать сущности.
Это неприемлемо.
Вот поведение, которое я хотел бы реализовать:
- если транзакции нет, загрузка не может быть отменена, считается зафиксированной
- если есть транзакция, которая фиксируется во время загрузки данных, обрабатывать загруженные данные как зафиксированные
- если есть откат транзакции, сбросьте статус
FooTestData
, если он не был зафиксирован ранее
Как мне это сделать?
Я пытался
object FooTestData{
class DataLoadedEvent(source:Any):ApplicationEvent(source)
private val eventMulticaster = SimpleApplicationEventMulticaster()
init {
eventMulticaster.setTaskExecutor(SimpleAsyncTaskExecutor())
}
internal var isCommitted = false
internal var isLoaded = false
set(value) {
field = value
if(value) eventMulticaster.multicastEvent(DataLoadedEvent(this))
}
var fooID = -1L
internal set
var barID = -1L
internal set
}
@Configuration
class FooTestDataConfiguration{
@TransactionalEventListener(phase = TransactionPhase.AFTER_COMMIT)
fun onCommit(event:FooTestData.DataLoadedEvent){
println("onCommit, $event")
if(FooTestData.isLoaded) {
FooTestData.isCommitted = true
}
}
@TransactionalEventListener(phase = TransactionPhase.AFTER_ROLLBACK)
fun afterRollback(event:FooTestData.DataLoadedEvent){
println("afterRollback, $event")
if(!FooTestData.isCommitted) {
FooTestData.isLoaded = false
}
}
}
fun TestDataInserter.fooTestData(){
if(FooTestData.isLoaded) return
FooTestData.isLoaded = true
/* TODO: figure out how to do this
if(there_is_no_transaction){
FooTestData.isCommitted = true
}
*/
with(FooTestData){
fooID = insertNewFoo("foo")
barID = insertNewFoo("bar")
}
}
в двух разных транзакциях (которые я откатил), но я, должно быть, что-то неправильно понял, потому что эти TransactionalEventListeners абсолютно ничего не сделали.
Как получить нужную функциональность?