Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Unable to create entity with overridden equals method due to field initialization error #806

Closed
dannyim opened this issue Feb 22, 2020 · 2 comments
Assignees
Labels

Comments

@dannyim
Copy link

dannyim commented Feb 22, 2020

The code below works on version 0.13.7:

object Cats: IntIdTable() {
    val name = varchar("name", 64)
}

class Cat(id: EntityID<Int>): IntEntity(id) {
    companion object : IntEntityClass<Cat>(Cats)
    var name by Cats.name

    override fun equals(other: Any?): Boolean {
        if(other == null) {
            return false
        }
        return if(other is Cat) {
            name == other.name
        } else {
            false
        }
    }
}

fun main(args: Array<String>) {
    Database.connect("jdbc:h2:mem:test", driver = "org.h2.Driver")

    transaction {
        SchemaUtils.create(Cats)
        val cat = Cat.new(1) {
            name = "Hamilton"
        }
    }
}

But after updating to 0.21.1 I am getting the following error:

Exception in thread "main" java.lang.IllegalStateException: com.example.Cats.name is not initialized yet
	at org.jetbrains.exposed.sql.ResultRow.rawToColumnValue(ResultRow.kt:44)
	at org.jetbrains.exposed.sql.ResultRow.get(ResultRow.kt:25)
	at org.jetbrains.exposed.dao.Entity.lookup(Entity.kt:96)
	at org.jetbrains.exposed.dao.Entity.getValue(Entity.kt:82)
	at com.example.Cat.getName(App.kt)
	at com.example.Cat.equals(App.kt:33)
	at kotlin.jvm.internal.Intrinsics.areEqual(Intrinsics.java:162)
	at org.jetbrains.exposed.dao.EntityClass.invalidateEntityInCache$exposed_dao(EntityClass.kt:67)
	at org.jetbrains.exposed.dao.Entity.setValue(Entity.kt:100)
	at com.example.Cat.setName(App.kt)
	at com.example.AppKt$main$1$cat$1.invoke(App.kt:46)
	at com.example.AppKt$main$1$cat$1.invoke(App.kt)
	at org.jetbrains.exposed.dao.EntityClass.new(EntityClass.kt:243)
	at com.example.AppKt$main$1.invoke(App.kt:45)
	at com.example.AppKt$main$1.invoke(App.kt)
	at org.jetbrains.exposed.sql.transactions.ThreadLocalTransactionManagerKt$inTopLevelTransaction$1.invoke(ThreadLocalTransactionManager.kt:156)
	at org.jetbrains.exposed.sql.transactions.ThreadLocalTransactionManagerKt$inTopLevelTransaction$2.invoke(ThreadLocalTransactionManager.kt:197)
	at org.jetbrains.exposed.sql.transactions.ThreadLocalTransactionManagerKt.keepAndRestoreTransactionRefAfterRun(ThreadLocalTransactionManager.kt:205)
	at org.jetbrains.exposed.sql.transactions.ThreadLocalTransactionManagerKt.inTopLevelTransaction(ThreadLocalTransactionManager.kt:196)
	at org.jetbrains.exposed.sql.transactions.ThreadLocalTransactionManagerKt$transaction$1.invoke(ThreadLocalTransactionManager.kt:134)
	at org.jetbrains.exposed.sql.transactions.ThreadLocalTransactionManagerKt.keepAndRestoreTransactionRefAfterRun(ThreadLocalTransactionManager.kt:205)
	at org.jetbrains.exposed.sql.transactions.ThreadLocalTransactionManagerKt.transaction(ThreadLocalTransactionManager.kt:106)
	at org.jetbrains.exposed.sql.transactions.ThreadLocalTransactionManagerKt.transaction(ThreadLocalTransactionManager.kt:104)
	at org.jetbrains.exposed.sql.transactions.ThreadLocalTransactionManagerKt.transaction$default(ThreadLocalTransactionManager.kt:103)
	at com.example.AppKt.main(App.kt:43)

Within EntityClass.kt I see:

    internal open fun invalidateEntityInCache(o: Entity<ID>) {
        val entityAlreadyFlushed = o.id._value != null
        val sameDatabase = TransactionManager.current().db == o.db
        if (entityAlreadyFlushed && sameDatabase) {
            val currentEntityInCache = testCache(o.id)
            if (currentEntityInCache == null) {
                get(o.id) // Check that entity is still exists in database
                warmCache().store(o)
            } else if (currentEntityInCache != o) {
                exposedLogger.error("Entity instance in cache differs from the provided: ${o::class.simpleName} with ID ${o.id.value}. Changes on entity could be missed.")
            }
        }
    }

So this appears to be happening due to the newly created entity being compared to a cached instance. Since this is a newly created entity, why would the cache invalidation be performed?

@Tapac Tapac self-assigned this Mar 3, 2020
@Tapac Tapac added the bug label Mar 3, 2020
@Tapac
Copy link
Contributor

Tapac commented Mar 5, 2020

Fixed in master. Will be available in 0.22.1

@Tapac Tapac closed this as completed Mar 5, 2020
Tapac added a commit that referenced this issue Mar 5, 2020
@jerryOkafor
Copy link

I am still having this issue with 0.29.1:

UserSubscriptions.user_id is not initialized yet

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
Projects
None yet
Development

No branches or pull requests

3 participants