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

Missing way to locate by EntityId #38

Closed
jansorg opened this issue Dec 20, 2017 · 4 comments
Closed

Missing way to locate by EntityId #38

jansorg opened this issue Dec 20, 2017 · 4 comments
Assignees

Comments

@jansorg
Copy link

jansorg commented Dec 20, 2017

I couldn't find a way to load an XdEntity by EntityId (a string with a value of an EntityId).

I guess that there's a better way, but here's my code to to this:

import kotlinx.dnq.XdEntity
import kotlinx.dnq.XdNaturalEntityType

open class XdCustomEntityType<T : XdEntity>() : XdNaturalEntityType<T>(storeContainer = ThreadLocalStoreContainer) {
    fun find(id: String): T? {
        val transaction = (XdOrganisation.entityStore.threadSession
                ?: throw IllegalStateException("New entities can be created only in transactional block"))

        val entity = transaction.getEntity(transaction.toEntityId(id))
        return wrap(entity).apply {
            constructor()
        }
    }
}
@sedovalx
Copy link
Contributor

EntityId is a low level class. Why do you need to search by it? Usually, you have an identity field in a base class of your xd-hierarchy:

abstract class XdIdEntityType<XD : XdIdEntity> : XdNaturalEntityType<XD>(ThreadLocalStoreContainer) {
    fun findById(id: Long): XD? {
        return all().firstOrNull(XdIdEntity::id eq id)
    }
}

abstract class XdIdEntity(entity: Entity) : XdEntity(entity) {
    companion object : XdIdEntityType<XdIdEntity>()
    
    val id by xdRequiredLongProp(unique = true) { min(0) }
}

And there is a kind of agreement that all operations over xd-entities that involve data reads or writes should be done in a transactional block. So, typically, there is no need to check the current transaction in xd-methods.
Anyway, you are on a right way if you think you need to search by an EntityId. Here is how I would do it:

val store: TransientEntityStore = TODO()
val entityId: String = TODO()
        
store.transactional { txn ->
    txn.getEntity(txn.toEntityId(entityId)).toXd<XdMyEntity>()
}

@lehvolk lehvolk self-assigned this Dec 21, 2017
@jansorg
Copy link
Author

jansorg commented Dec 22, 2017

Thanks @sedovalx ,
I couldn't find a way to have an automatically generated UUID in my entities, so I used the internal id (as suggest at https://github.com/JetBrains/xodus/wiki/Entity-Stores#entities at the end).

I'm now using a halfway automatic solution using UUIDs and a find operation like you suggested.

@sedovalx
Copy link
Contributor

sedovalx commented Dec 23, 2017

You can use UUID.randomUUID().toString() in a constructor of your xd-entities:

abstract class XdIdEntityType<XD : XdIdEntity> : XdNaturalEntityType<XD>(ThreadLocalStoreContainer) {
    fun findById(id: String): XD? {
        return all().firstOrNull(XdIdEntity::id eq id)
    }
}

abstract class XdIdEntity(entity: Entity) : XdEntity(entity) {
    companion object : XdIdEntityType<XdIdEntity>()

    var id by xdRequiredStringProp(unique = true, trimmed = true)

    override fun constructor() {
        this.id = UUID.randomUUID().toString()
    }

    override fun beforeFlush() {
        if (!isNew && hasChanges(XdIdEntity::id)) {
            throw DataConstraintsException("It is not allowed to change ID after construction")
        }
    }
}

class XdMyEntity(entity: Entity) : XdIdEntity(entity) {
    companion object : XdIdEntityType<XdMyEntity>() {
        fun new(value: Int) = new {
            this.value = value
        }
    }

    override fun constructor() {
        super.constructor()
        this.defaultProp = "default value"
    }

    var value by xdIntProp()
    var defaultProp by xdStringProp()
}

And then val xd = XdMyEntity.new(42).

@lehvolk
Copy link
Contributor

lehvolk commented Dec 24, 2017

@sedovalx EntityId is a reliable database identity which can be used as unique entity identity across single database. At the moment we have only one implementation of EntityId for which toString will return string identity like typeId-entityLocalId. Backward API is not supported in xodus-dnq at the moment thus you should make a low-level call tx.getEntity(tx.toEntityId(entityStringId)).toXd().

I think we should definitely support converting EntityId to String and back and type safe search by id across database.

lehvolk added a commit that referenced this issue Dec 27, 2017
@lehvolk lehvolk closed this as completed Dec 27, 2017
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

3 participants