一键导入
repository
Repository-mønster med Kotlin object og Connection/TransactionalSession extension-funksjoner, DBUtils-transaksjoner og ResultSet-mapping
用 Codex 或 Claude 帮你安装 复制这段 Prompt,粘贴到 Codex、Claude 或其他助手里,让它检查 Skill 页面并帮你完成安装。
菜单
Repository-mønster med Kotlin object og Connection/TransactionalSession extension-funksjoner, DBUtils-transaksjoner og ResultSet-mapping
用 Codex 或 Claude 帮你安装 复制这段 Prompt,粘贴到 Codex、Claude 或其他助手里,让它检查 Skill 页面并帮你完成安装。
基于 SOC 职业分类
| name | repository |
| description | Repository-mønster med Kotlin object og Connection/TransactionalSession extension-funksjoner, DBUtils-transaksjoner og ResultSet-mapping |
Repository- og databaseaksessmønstre: object-repositories med Connection-extensions, DBUtils-transaksjoner, ResultSet-mapping og feilhåndtering.
All database access goes through
DBUtils.asyncTransaction {}(suspending) orDBUtils.transaction {}(blocking). Repositories are Kotlinobjects with extension functions onConnectionorTransactionalSession.
PostgresDataSource is a singleton object using HikariCP. In non-local environments it integrates with Vault for credentials:
object PostgresDataSource {
val dataSource: HikariDataSource by lazy { dataSource() }
fun migrate() {
dataSource(role = postgresConfig.adminUser).use { migrate(it) }
}
fun migrate(dataSource: HikariDataSource) {
Flyway.configure()
.dataSource(dataSource)
.initSql("""SET ROLE "${postgresConfig.adminUser}"""")
.lockRetryCount(-1)
.validateMigrationNaming(true)
.load()
.migrate()
}
}
Always use DBUtils.asyncTransaction {} (suspending) or DBUtils.transaction {} (blocking). Never use bare JDBC connections directly.
// Suspending (use in coroutine context / service layer)
dataSource.asyncTransaction { session ->
KravRepository.run { session.insertAllNewKrav(kravLinjer, filnavn) }
}
// Blocking (use in sync contexts)
dataSource.transaction { session ->
KravRepository.run { session.updateStatus(corrId, status) }
}
Repositories are Kotlin objects with extension functions on Connection (raw JDBC) or TransactionalSession (kotliquery). Use RepositoryExtensions helpers:
object KravRepository {
fun Connection.getAllUnsentKrav() =
executeSelect(
"""select * from krav where status = ?""",
Status.KRAV_IKKE_SENDT.value,
).toKrav()
fun Connection.updateSentKrav(
corrId: String,
kravidentifikatorSKE: String,
status: String,
) = executeUpdate(
"""update krav set kravidentifikator_ske = ?, status = ?, tidspunkt_sendt = now() where corr_id = ?""",
kravidentifikatorSKE,
status,
corrId,
)
// For kotliquery TransactionalSession (e.g. when returnGeneratedKey is needed)
fun getKravTableIdFromCorrelationId(
tx: TransactionalSession,
corrID: String,
): Long =
tx.single(
queryOf("select id from krav where corr_id = ?", corrID)
.map { row -> row.long("id") }
.asSingle,
) ?: throw IllegalStateException("Krav med corrId $corrID ikke funnet")
}
Centralise ResultSet → domain mapping in RepositoryMappers.kt using getColumn<T>():
fun ResultSet.toKrav() =
toList {
Krav(
kravId = getColumn("id"),
saksnummerNAV = getColumn("saksnummer_nav"),
status = getColumn("status"),
kravtype = getColumn("kravtype"),
corrId = getColumn("corr_id"),
kravidentifikatorSKE = getColumn("kravidentifikator_ske"),
// ... remaining fields
)
}
private fun <T> ResultSet.toList(mapper: ResultSet.() -> T) =
buildList {
while (next()) { add(mapper()) }
}
Wrap bare Connection usage with useAndHandleErrors:
dataSource.connection.useAndHandleErrors { con ->
con.getAllUnsentKrav()
}
DBUtils.asyncTransaction {} / DBUtils.transaction {} — never bare Connection in service codeobject + extension functions for repositoriesResultSet → domain in RepositoryMappers.kt using getColumn<T>()Connection usage with useAndHandleErrorsRepositoryMappers.ktFlyway-migrasjoner for PostgreSQL: navnekonvensjoner (V{n}__desc.sql), skjema for krav/feilmelding/filvalideringsfeil, DBListener-testing med TestContainers
Post-send livssyklus: StatusService poller /mottaksstatus; StoppKravService; RapportService + AvstemmingRouting-frontend for manuell reskontroføring
HOCON-basert konfigurasjon med PropertiesConfig singleton for Ktor batch-tjenester på NAIS (FSS)
SlackService feilakkumulering og Tags-basert varsling for prosesseringsfeil i SKE-batch
Endring av eksisterende krav (endre rente og endre hovedstol): EndreKravService, request-DTOer, status-konformering og SKE API PUT-endepunkter
Kotest BehaviorSpec/MockK-mønstre for sokos-ske-krav: scenariostruktur, DBListener/SftpListener, MockHttpClient, circuit-breaker-reset og matchers