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

Added supporter for custom mappers column to entityand entity to column #128

Open
guitcastro opened this issue Jan 17, 2023 · 3 comments
Open

Comments

@guitcastro
Copy link

Hi! First of all thanks for the amazing project! I am evaluating it, and loving it =)

My goals is have a small orm to mapper tables entity to domain entities and vice-versa, and if possible without an intermediate entities. Per example, the following domain class:


data class Foo(val id: Id, val name: String) {
    @JvmInline
    value class Id(val value: UUID = UUID.randomUUID())
}

Would be really coll if this was possible:


object FooSchema : PostgresqlTable<Foo> {
    val id = uuid({ it.id.value }).primaryKey()
    val name = varchar(Foo::name)
}

This does not work because getters are restricted to KCallable:


// Reflection.kt
public fun <T : Any> ((T) -> Any?).toCallable(): KCallable<Any?> =
        when (this) {
            is KProperty1<T, *> -> this
            is KFunction<*> -> this
            else -> throw RuntimeException("Wrong type for $this, support only KProperty1 and KFunction")
        }

I've done the follow workaround and it worked partially:


object FooSchema : PostgresqlTable<Foo>() {
    val id = uuid(Foo::id).primaryKey()
}
private fun Foo.id() = this.id.value

I mean partially, because it's possible to insert rows, but this breaks reading entities from database. The exception occur at:

callBy(args)

because: kotysaTable.columns.indexOf(column) is an UUID and not a column.columnClass.javaObjectType

  args[param] =
              row.getWithOffset(kotysaTable.columns.indexOf(column), column.columnClass.javaObjectType)


So if we add a property to KotysaColumnDb<T : Any, U : Any> such as :

public val rowToEntityConverter: (U -> T), would be possible to use custom mapper (at least from row to entities) using:


  val rawColumnValue = row.getWithOffset(kotysaTable.columns.indexOf(column), column.columnClass.javaObjectType)
  args[param] =  column.rowToEntityConverter.call(rawColumnValue)

If this is in the scope of the project and I am in the right track to implement it, I can open a PR to fix it.

@pull-vert
Copy link
Contributor

Hi @guitcastro , first thanks a lot for the kind words about Kotysa 🙂

An issue was opened a few weeks ago, I think you can take a look the 2 solutions I gave at that time.
I think they could solve your case without needing a new feature in Kotysa : #100

A custom converter could be a great feature for Kotysa, but Kotlin language has already very nice native features like the by keyword so I am not sure this is needed.

If the solutions I gave in #100 drive you to a clean answer for your particular case, maybe you can reply in a new comment with the code you ended with ?
It would provide an example that I can share in Kotysa documentation.

@guitcastro
Copy link
Author

I've looked, and using the by keyword in a extension enforces me to add a default value to my domain constructor, which is not desired. I tried to use noArg kotlin plugin, however the constructor is generated only for java Class and not for KClass. One option is to verify if the class has a java 0 args constructor and if so, use it and initialize all other properties later.

This would fill my needs, as I am adding a noArg but it only can be used by reflection. So the domain remains clean.

@pull-vert
Copy link
Contributor

Hi @guitcastro

I am currently working on Kotysa 3.0, with nice and big technical changes. I will have a look at this issue after that :)

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

2 participants