帮助开发者掌握 Kotlin Exposed ORM 的查询、事务与迁移实践
复制安装指令,让 AI 自动完成配置 · 推荐新手
请帮我安装 askskill 上的 "kotlin-exposed-patterns" 技能: 1. 下载 https://raw.githubusercontent.com/affaan-m/ECC/main/docs/ja-JP/skills/kotlin-exposed-patterns/SKILL.md 2. 保存为 ~/.claude/skills/kotlin-exposed-patterns/SKILL.md 3. 装好后重载技能,告诉我可以用了
请用 Kotlin Exposed 为用户表编写 DSL 查询示例,包含按状态筛选、按创建时间倒序排序、分页,并解释每段代码作用。
一段可复用的 Exposed DSL 查询代码,并附带逐段说明与适用场景。
请基于 Kotlin Exposed 设计 DAO 模式与 Repository 模式的示例,展示用户实体的新增、查询、更新与删除,并说明两种模式如何配合。
包含实体、DAO、仓储接口与实现的完整示例,以及模式选型建议。
请给出 Kotlin Exposed 集成 HikariCP 和 Flyway 的项目配置示例,包含数据库连接、事务管理、启动时自动迁移,以及生产环境注意事项。
一套可落地的数据库基础设施配置方案,含关键代码、配置项与最佳实践说明。
JetBrains Exposed ORM を使用したデータベースアクセスの包括的なパターン(DSL クエリ、DAO、トランザクション、プロダクション対応の設定を含む)。
Exposed は 2 つのクエリスタイルを提供します: 直接 SQL に似た表現のための DSL と、エンティティライフサイクル管理のための DAO です。HikariCP は HikariConfig を通じて設定された再利用可能なデータベース接続のプールを管理します。Flyway はスタートアップ時にバージョン管理された SQL マイグレーションスクリプトを実行してスキーマを同期させます。すべてのデータベース操作はコルーチンの安全性とアトミシティのために newSuspendedTransaction ブロック内で実行されます。リポジトリパターンはビジネスロジックをデータレイヤーから切り離し、テストがインメモリ H2 データベースを使用できるようにします。
suspend fun findUserById(id: UUID): UserRow? =
newSuspendedTransaction {
UsersTable.selectAll()
.where { UsersTable.id eq id }
.map { it.toUser() }
.singleOrNull()
}
suspend fun createUser(request: CreateUserRequest): User =
newSuspendedTransaction {
UserEntity.new {
name = request.name
email = request.email
role = request.role
}.toModel()
}
val hikariConfig = HikariConfig().apply {
driverClassName = config.driver
jdbcUrl = config.url
username = config.username
password = config.password
maximumPoolSize = config.maxPoolSize
isAutoCommit = false
transactionIsolation = "TRANSACTION_READ_COMMITTED"
validate()
}
// DatabaseFactory.kt
object DatabaseFactory {
fun create(config: DatabaseConfig): Database {
val hikariConfig = HikariConfig().apply {
driverClassName = config.driver
jdbcUrl = config.url
username = config.username
password = config.password
maximumPoolSize = config.maxPoolSize
isAutoCommit = false
transactionIsolation = "TRANSACTION_READ_COMMITTED"
validate()
}
return Database.connect(HikariDataSource(hikariConfig))
}
}
data class DatabaseConfig(
val url: String,
val driver: String = "org.postgresql.Driver",
val username: String = "",
val password: String = "",
val maxPoolSize: Int = 10,
)
// FlywayMigration.kt
fun runMigrations(config: DatabaseConfig) {
Flyway.configure()
.dataSource(config.url, config.username, config.password)
.locations("classpath:db/migration")
.baselineOnMigrate(true)
.load()
.migrate()
}
// アプリケーションスタートアップ
fun Application.module() {
val config = DatabaseConfig(
url = environment.config.property("database.url").getString(),
username = environment.config.property("database.username").getString(),
password = environment.config.property("database.password").getString(),
)
runMigrations(config)
val database = DatabaseFactory.create(config)
// ...
}
-- src/main/resources/db/migration/V1__create_users.sql
CREATE TABLE users (
id UUID PRIMARY KEY DEFAULT gen_random_uuid(),
name VARCHAR(100) NOT NULL,
email VARCHAR(255) NOT NULL UNIQUE,
role VARCHAR(20) NOT NULL DEFAULT 'USER',
metadata JSONB,
created_at TIMESTAMPTZ NOT NULL DEFAULT NOW(),
updated_at TIMESTAMPTZ NOT NULL DEFAULT NOW()
);
CREATE INDEX idx_users_email ON users(email);
CREATE INDEX idx_users_role ON users(role);
// tables/UsersTable.kt
object UsersTable : UUIDTable("users") {
val name = varchar("name", 100)
val email = varchar("email", 255).uniqueIndex()
val role = enumerationByName<Role>("role", 20)
val metadata = jsonb<UserMetadata>("metadata", Json.Default).nullable()
val createdAt = timestampWithTimeZone("created_at").defaultExpression(CurrentTimestampWithTimeZone)
…
通过双评审智能体对结果进行对抗式校验,提升输出发布前的可靠性
提供地道 Kotlin 设计模式与最佳实践,帮助构建健壮高效且易维护的应用