Exposed: No exception on update

Created on 23 May 2020  路  2Comments  路  Source: JetBrains/Exposed

Hi, I'm using Exposed for the first time to build an application to view and edit data on a database.
To do this I use DAO and I keep data objects saved after retrieving them from the database.
When I try to update an object with a wrong value I expect to receive an exception I can handle, but the transaction terminates with no errors and the value on the local object remains the wrong one. If I try to refetch the object from the database I get the old value (of course, the database didn't allow writing a wrong value).
Here's a simple example:

var step = transaction { Step.all().first() }
println("Number before update ${step.number}")
for (i in 1..2) {
    try {
        transaction {
            addLogger(StdOutSqlLogger)
            step.number = -1
        }
    } catch (e: SQLException) {
        println("didnt work")
    }
}
println("Number after update ${step.number}")
step = transaction { Step.all().first() }
println("Number after refetch ${step.number}")

and the output is

Number before update 2
SQL: SELECT step.id, step.adventure, step."number", step."text", step.loot FROM step WHERE step.id = 2
SQL: UPDATE step SET "number"=-1 WHERE id = 2
SQL: SELECT step.id, step.adventure, step."number", step."text", step.loot FROM step WHERE step.id = 2
SQL: SELECT step.id, step.adventure, step."number", step."text", step.loot FROM step WHERE step.id = 2
Number after update -1
Number after refetch 2

The Step class is declared as follows

object Steps : AdventureTable("STEP") { // AdventureTable just declares the adventure field
    val number = integer("number").check { it greaterEq Step.MIN_NUMBER }
    val text = text("text")

    init {
        uniqueIndex(adventure, number)
    }
}
class Step(id: EntityID<Int>) : IntEntity(id) {
    companion object : IntEntityClass<Step>(Steps) {
        const val MIN_NUMBER = 1
    }

    var number by Steps.number
    var text by Steps.text

    var adventure by Adventure referencedOn Steps.adventure
}

EDIT: fixed table declaration

bug

Most helpful comment

I'm using PostgreSQL version 9.6.17.

Looking deeper with a debugger, seems that the following events occur:

  1. commit() on the transaction
  2. The entity cache is flushed
  3. The transaction is sent to the database, but fails with an exception
  4. The exception is handled, but since since repetitionAttempts is not reached yet (looking at the run method of ThreadLocalTransactionManager) it is ignored before retrying
  5. Everything is done again, but since the cache has been flushed there is nothing to commit anymore so the commit ends

This is what I understood looking at the code and the execution. Maybe the only problem is that the entityCache is flushed before being sure the transaction was successful..? Just guessing

All 2 comments

What database do you use?

I'm using PostgreSQL version 9.6.17.

Looking deeper with a debugger, seems that the following events occur:

  1. commit() on the transaction
  2. The entity cache is flushed
  3. The transaction is sent to the database, but fails with an exception
  4. The exception is handled, but since since repetitionAttempts is not reached yet (looking at the run method of ThreadLocalTransactionManager) it is ignored before retrying
  5. Everything is done again, but since the cache has been flushed there is nothing to commit anymore so the commit ends

This is what I understood looking at the code and the execution. Maybe the only problem is that the entityCache is flushed before being sure the transaction was successful..? Just guessing

Was this page helpful?
0 / 5 - 0 ratings

Related issues

power721 picture power721  路  3Comments

coolemza picture coolemza  路  3Comments

BugsBunnyBR picture BugsBunnyBR  路  3Comments

yuri-li picture yuri-li  路  3Comments

vasily-kirichenko picture vasily-kirichenko  路  4Comments