使用TransactionalEventListener设置回滚标志?

时间:2019-04-25 14:22:36

标签: java spring spring-boot kotlin spring-transactions

所以我有一种将一些测试数据加载到数据库中的方法。

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")
    }
}

BUT 如果回滚发生的交易(如果有交易)怎么办?

然后,我们在数据库中没有实体,FooTestData对象中的ID无效,并且设置了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")
    }
}

在两个不同的事务中(我回滚了),但是我一定对某些事情有误解,因为这些TransactionalEventListener绝对没有做任何事情。

我如何获得所需的功能?

0 个答案:

没有答案