dave08
01/11/2024, 10:23 AM@KomapperProjection
a @KomapperEntity
? It's a bit confusing, since it's not really in the database... and sometimes might not have any relationship to something in the database... (is there a Meta entry generated for it? What would be it's use?). Also it seems like it needs a @KomapperId
even though a projection might not always have one... And it doesn't seem to take into consideration nullable fields with default values... (you have to provide it, and it can't be null
...)
Also, can a projection be used to map the result from many joined tables?Toshihiro Nakamura
01/11/2024, 1:39 PMselectAsAddress
.
is there a Meta entry generated for it?Yes. The generated metamodel is used to instantiate a data class in a type-safe manner.
And it doesn’t seem to take into consideration nullable fields with default values.That is intentional. Komapper has not considered default values until now.
dave08
01/11/2024, 1:43 PMdave08
01/11/2024, 1:43 PMToshihiro Nakamura
01/12/2024, 1:07 PM@KomapperEntity
annotation, as in the following example. In this case, there is no need to annotate @KomapperId
.
@KomapperProjection
data class PersonDto(val name: String, val age: Int)
Toshihiro Nakamura
01/13/2024, 5:15 AMdave08
01/14/2024, 2:50 PMdave08
01/15/2024, 4:11 PMdave08
01/15/2024, 4:13 PMnull
in passed in to the selectAsXXX
functions would allow to skip passing those properties the the projection's constructor (thereby using the constructor's default value -- whether it may be null
or some other value).dave08
01/15/2024, 4:17 PM@KomapperProjection(propertiesWithDefaults=["prop1"])
or something like that...Toshihiro Nakamura
01/16/2024, 11:18 AMToshihiro Nakamura
01/16/2024, 11:18 AMat worst, if KSP doesn’t know it has a default value, maybe a special annotation could be used to tell it, or those properties could be listed in @KomapperProjection(propertiesWithDefaults=[“prop1”]) or something like that...I think using annotations is limited in expressiveness because annotations only support specific types.
dave08
01/16/2024, 11:19 AMdave08
01/16/2024, 11:23 AMdave08
01/16/2024, 11:26 AM@KomapperProjection
data class Proj(val foo: String?)
query.selectAsProj(foo = // how would I set this to null if needed?
)
dave08
01/16/2024, 11:28 AMColumnExpression<String, String>?
where null represents "use a default value", whereas ColumnExpression<String?, String?>
set the field's value to null
in the db (although there seems to be no such thing as literal(null)
...).dave08
01/16/2024, 11:31 AMToshihiro Nakamura
01/16/2024, 11:49 AMquery.selectAsProj(foo = // how would I set this to null if needed?
)
I plan to add a null expression to represent NULL in SQL.
query.selectAsProj(foo = nullLiteral())
Toshihiro Nakamura
01/16/2024, 11:51 AMIt seems like there’s a way to know if there’s a default argument there in KSP...KSP knows whether there is a default value, but it cannot retrieve the default value.
dave08
01/16/2024, 11:52 AMToshihiro Nakamura
01/16/2024, 12:16 PMdave08
01/16/2024, 12:32 PM@KomapperProjection
data class Proj(val id: Int, val foo: String?)
...
override fun newEntity(m: Map<org.komapper.core.dsl.metamodel.PropertyMetamodel<*, *, *>, Any?>) = Proj(
// By default, only instantiate with required arguments.
`id` = m[this.`id`] as Int,
).let { proj ->
// not sure about this check, but whatever it takes to check if it has a default argument...
m[this.`name`]?.let { proj.copy(name = it) }
}
But, yeah, I agree it would be a bit messy 🤔, and then if there's a bunch of them... 🤕dave08
01/16/2024, 12:39 PMselectAsXXX
function, I guess that would have been ideal... for simple defaults, that could be done with some kind of annotation on the property to specify the type and value... but that's a bit more limiting than actually using the default values themselves...dave08
01/16/2024, 1:43 PMToshihiro Nakamura
01/16/2024, 1:58 PMselectAsProj(foo = coalesce(p.foo, literal("default")))
See also https://www.komapper.org/docs/reference/query/querydsl/expression/#conditional-expression-coalescedave08
01/16/2024, 2:06 PMp.foo
to put there in the first place...dave08
01/16/2024, 2:07 PMdave08
01/16/2024, 2:08 PM@KomapperProjection
data class Foo(val bar: Bar)
@KomapperProjection
data class Bar(val id: Int, val baz: String)
query.selectAsFoo(bar = Bar(p.id, p.bar))
dave08
01/16/2024, 2:10 PMdave08
01/16/2024, 2:12 PMval addresses: List<Address>
...dave08
01/16/2024, 2:14 PMEntityStore
...Toshihiro Nakamura
01/16/2024, 2:18 PM@KomapperProjection
data class Foo(@KomapperEmbedded val bar: Bar)
data class Bar(val id: Int, val baz: String)
query.selectAsFoo(`bar#id` = p.id, `bar#baz` = p.bar))
dave08
01/16/2024, 2:44 PMToshihiro Nakamura
01/16/2024, 3:00 PM