Using `QueryDsl.insert(..).values { ... }` when le...
# komapper
d
Using
QueryDsl.insert(..).values { ... }
when leaving out properties with a default value in the entity data class doesn't insert them automatically in the values block? I could use the
single(...)
form, but then I'd have to include my createdAt and updatedAt properties that I'd like Komapper to fill in for me...
t
How about setting default values for the createdAt and updatedAt properties and using
single()
? That way, you won’t need to explicitly set values for the createdAt and updatedAt properties.
d
It's not too nice for unit tests that I need to override the Kotlinx datetime Clock with a TestClock instance that now() is a fixed time...
But the truth is, that even Komapper uses it's own clock instance... so I wouldn't be gaining much 🤕
Now I remember, you have a
ClockProvider
...
That's why I rathered use Komapper to generate them
And anyways, I usually use DI for all dependencies, I wouldn't really like to create a global top level property for Clock...
t
I may not understand what you’re trying to achieve, but by using a ClockProvider, you can generate a specific time during testing and set it to the createdAt and updatedAt properties. I think it’s also possible to manage the implementation of the ClockProvider with a DI container.
d
You're suggesting to do this:
Copy code
@KomapperEntity
...
data class Foo(
...
   val bar: Int = 1,
   @KomapperCreatedAt
   val createdAt: LocalDateTime = globalClock.now().toLocalDateTime()
)
And then use single(...) with that? Then it doesn't use
@KomapperCreatedAt
at all, but rather a global clock I provide...
🚫 1
So then I misunderstood...
The other option is that you're suggesting to make them nullable and setting them to null for Komapper to handle generating them, but then in the underlying db they're not null, and accessing the property everywhere would require
!!
...
This is exactly the reason why I used
values { }
here... but then I loose the defaults
t
How about this?
Copy code
@KomapperEntity
data class Address(
    @KomapperId
    @KomapperAutoIncrement
    val id: Int = 0,
    val street: String,
    @KomapperCreatedAt
    val createdAt: LocalDateTime = LocalDateTime.MIN,
    @KomapperUpdatedAt
    val updatedAt: LocalDateTime = LocalDateTime.MIN,
)

fun main() {
    val db = JdbcDatabase("jdbc:h2:mem:example;DB_CLOSE_DELAY=-1", clockProvider = { Clock.fixed(Instant.EPOCH, ZoneId.systemDefault()) })
    
    val a = Meta.address

    db.withTransaction {
        db.runQuery {
            QueryDsl.create(a)
        }
        val newAddress = db.runQuery {
            // insert into ADDRESS (STREET, CREATED_AT, UPDATED_AT) values ('street A', '1970-01-01T09:00', '1970-01-01T09:00')
            QueryDsl.insert(a).single(Address(street = "street A"))
        }
    }
}
d
Interesting! But from here I understand that Komapper doesn't set those properties to what I set them to just like
@KomapperAutoIncrement
?
Or is this the behavior only with
LocalDateTime.MIN
? I guess this is the same question for both... when Komapper tries to handle things is there a way to tell it that I want to override it's handling in certain cases, and only have it do what it wants when a certain default value is used?
Now I'm realising why the
values { }
doesn't work with default values, it's because ksp can't resolve that value... I remember seeing such an issue in another ksp lib... it's funny, I was half expecting that to work 🤷🏼‍♂️
t
If you use
insert(...).single(...)
, Komapper will always overwrite properties annotated with
@KomapperCreatedAt
or
@KomapperUpdatedAt
.
👍🏼 1
d
Only if they're provided though?
In your example above, MIN is actually being saved, or is Komapper generating it with the ClockProvider?
I'm juggling through TONS of test code that I need should pass, I really can't rewrite everything now to use a new method, so I'm trying to work around things...
t
In my example, Komapper is overwriting LocalDateTime.MIN with the value generated by ClockProvider.
👍🏼 1
d
So when using
values { }
Komapper doesn't do that then?
t
If you do not explicitly call the
eq
function for properties with the following mapping definitions then the value is automatically set in the generated SQL:
@KomapperSequence
@KomapperVersion
@KomapperCreatedAt
@KomapperUpdatedAt
If you explicitly call the
eq
function for those properties, the explicit value takes precedence.
The definition of
KomapperAutoIncrement
cannot be disabled with an explicit value.
See https://www.komapper.org/docs/reference/query/querydsl/insert/#values
👌🏼 1
d
Thanks a lot for all the help 😄, it's really appreciated!
👍 1