Skip to content

Instantly share code, notes, and snippets.

@nakamura-to
Last active July 27, 2024 12:58
Show Gist options
  • Save nakamura-to/ab905562e321bfc4603b07c82e887699 to your computer and use it in GitHub Desktop.
Save nakamura-to/ab905562e321bfc4603b07c82e887699 to your computer and use it in GitHub Desktop.
Komapperで複数エンティティに共通のプロパティを使ってクエリを組み立てる方法 (SELECTだけでなくUPDATEやDELETEにも対応)
package org.komapper.quickstart
import org.komapper.core.dsl.Meta
import org.komapper.core.dsl.QueryDsl
import org.komapper.jdbc.JdbcDatabase
import java.time.LocalDateTime
fun main() {
val database = JdbcDatabase("jdbc:h2:mem:quickstart;DB_CLOSE_DELAY=-1")
database.withTransaction {
database.runQuery {
QueryDsl.create(Meta.person, Meta.address)
}
// Personのクエリ
val p = Meta.person.asBiTemporal(1, LocalDateTime.now())
val query1 = QueryDsl.from(p).where {
p.name eq "Alice"
}
// Addressのクエリ
val a = Meta.address.asBiTemporal("Tokyo", LocalDateTime.now())
val query2 = QueryDsl.from(a).where {
a.city eq "Tokyo"
}
val query3 = QueryDsl.update(a).set {
a.city eq "Osaka"
}.where {
a.city eq "Tokyo"
}
val query4 = QueryDsl.delete(a).where {
a.city eq "Osaka"
}
// select t0_.id, t0_.name, t0_.age, t0_.valid_from, t0_.valid_to from person as t0_ where t0_.id = ? and t0_.valid_from <= ? and t0_.valid_to > ? and t0_.name = ?
database.runQuery(query1)
// select t0_.id, t0_.city, t0_.valid_from, t0_.valid_to from address as t0_ where t0_.id = ? and t0_.valid_from <= ? and t0_.valid_to > ? and t0_.city = ?
database.runQuery(query2)
// update address as t0_ set city = ? where t0_.id = ? and t0_.valid_from <= ? and t0_.valid_to > ? and t0_.city = ?
database.runQuery(query3)
// delete from address as t0_ where t0_.id = ? and t0_.valid_from <= ? and t0_.valid_to > ? and t0_.city = ?
database.runQuery(query4)
}
}
package org.komapper.quickstart
import org.junit.jupiter.api.Assertions.assertNull
import org.junit.jupiter.api.Test
import org.komapper.core.dsl.Meta
import org.komapper.core.dsl.QueryDsl
import org.komapper.core.dsl.query.dryRun
import java.time.LocalDateTime
class BiTemporalMetamodelTest {
@Test
fun test_person() {
val p = Meta.person.asBiTemporal(1, LocalDateTime.now())
val result = QueryDsl.from(p).dryRun()
assertNull(result.throwable)
}
@Test
fun test_address() {
val a = Meta.address.asBiTemporal("Tokyo", LocalDateTime.now())
val result = QueryDsl.from(a).dryRun()
assertNull(result.throwable)
}
}
package org.komapper.quickstart
import org.komapper.annotation.KomapperAutoIncrement
import org.komapper.annotation.KomapperEntity
import org.komapper.annotation.KomapperId
import org.komapper.core.dsl.expression.PropertyExpression
import org.komapper.core.dsl.metamodel.EntityMetamodel
import org.komapper.core.dsl.metamodel.define
import java.time.LocalDateTime
@KomapperEntity
data class Person(
@KomapperId
@KomapperAutoIncrement
val id: Int = 0,
val name: String,
val age: Int,
val validFrom: LocalDateTime,
val validTo: LocalDateTime,
)
@KomapperEntity
data class Address(
@KomapperId
val id: String = "",
val city: String,
val validFrom: LocalDateTime,
val validTo: LocalDateTime,
)
// デフォルトのWHERE句を持つメタモデルに変換
fun _Person.asBiTemporal(id: Int, date: LocalDateTime) = createBiTemporalMetamodel(this, id, date)
// デフォルトのWHERE句を持つメタモデルに変換
fun _Address.asBiTemporal(id: String, date: LocalDateTime) = createBiTemporalMetamodel(this, id, date)
fun <ENTITY: Any, ID: Any, META: EntityMetamodel<ENTITY, ID, META>> createBiTemporalMetamodel(base: META, id : ID, date: LocalDateTime): META {
return base.define { metamodel ->
val _id = metamodel.idProperties().single()
val _validFrom = metamodel.properties().single { it.name == "validFrom" }
val _validTo = metamodel.properties().single { it.name == "validTo" }
_id as PropertyExpression<ID, ID>
_validFrom as PropertyExpression<LocalDateTime, LocalDateTime>
_validTo as PropertyExpression<LocalDateTime, LocalDateTime>
where {
_id eq id
_validFrom lessEq date
_validTo greater date
}
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment