0Pricing
Kotlin Academy · 课时

Exposed DAO:实体类与关系

使用 DAO API 将表映射为实体类,并浏览实体之间的关系。

Exposed DAO:实体类与关系 是 CoddyKit 上的免费 Kotlin Academy 课时。 这是第 4 节课,共 4 节。 你可以在下方免费阅读本课时的完整内容 — 然后在浏览器中使用内置代码编辑器和全天候 AI 导师进行实践。 这是 Kotlin Academy 学习路径的一部分,你的进度在网页和 CoddyKit 应用中同步。 Kotlin Academy 课程共包含 4 节课。

什么是 Exposed DAO 层

Exposed DAO(数据访问对象)层通过活动记录风格的接口封装查询 DSL。您可以定义映射到表行的 Entity 子类,并直接读写实体实例上的属性。

定义实体

将 LongIdTable 与一个 Entity 子类配对。每个实体类都有一个伴生 EntityClass,负责处理查询:

object Users : LongIdTable("users") {
    val name  = varchar("name", 100)
    val email = varchar("email", 255)
}

class User(id: EntityID<Long>) : LongEntity(id) {
    companion object : LongEntityClass<User>(Users)
    var name  by Users.name
    var email by Users.email
}

创建实体

在 transaction { } 中使用 Entity.new { } 创建新行,并返回一个实体实例:

val alice: User = transaction {
    User.new {
        name  = "Alice"
        email = "alice@example.com"
    }
}

查找实体

伴生 EntityClass 提供以下查找方法:findById(id)、all() 和 find { condition }:

transaction {
    val user: User? = User.findById(1L)
    val allUsers: SizedIterable<User> = User.all()
    val filtered = User.find { Users.name like "Al%" }.toList()
}

更新实体

读取实体,在事务中修改其属性,Exposed 会在事务提交时自动发出 UPDATE:

transaction {
    val user = User.findById(1L) ?: error("Not found")
    user.name = "Alice Smith"
    // UPDATE issued on transaction commit
}

删除实体

在事务中调用 entity.delete(),即可删除对应的行:

transaction {
    User.findById(5L)?.delete()
}

一对多关系

在表上使用 reference(),并在实体上使用委托的 by 属性,即可让子实体引用父实体。通过 referrersOn,可以从父实体访问子实体列表:

object Posts : LongIdTable("posts") {
    val title    = varchar("title", 300)
    val authorId = reference("author_id", Users)
}
class Post(id: EntityID<Long>) : LongEntity(id) {
    companion object : LongEntityClass<Post>(Posts)
    var title  by Posts.title
    var author by User referencedOn Posts.authorId
}
// On User entity:
val posts by Post referrersOn Posts.authorId

多对多关系

请使用中间连接表。将其公开为 EntityClass,并通过 via() 访问关系的两端:

object UserRoles : Table("user_roles") {
    val user = reference("user_id", Users)
    val role = reference("role_id", Roles)
}
// On User entity:
var roles by Role via UserRoles

预加载与懒加载

默认情况下,Exposed 会以懒加载方式加载关联实体——每次访问都会触发一次 SQL 查询。使用 load() 或 with() 预加载关系,以避免 N+1 查询问题:

transaction {
    User.all().with(User::posts).forEach { user ->
        println("${user.name}: ${user.posts.count()} posts")
    }
}

事务内缓存

Exposed 会在事务内缓存实体实例。在同一事务中多次按 ID 访问同一实体时,会返回同一个内存对象,不会产生多余的数据库往返。

何时使用 DAO 而非查询 DSL

如果您需要面向对象的访问模式和关系,请使用 DAO 层。如果需要批量操作、复杂连接、聚合,或者性能很重要且需要精确控制 SQL,请使用查询 DSL。

快速检查

如何使用 Exposed DAO 创建新行并立即获取实体实例?

回顾:Exposed DAO — 实体类与关系

关键要点:

  • 将 LongIdTable 与 LongEntity 子类配对;属性委托给列定义
  • Entity.new { } — 创建;findById()、find { }、all() — 查询;entity.delete() — 删除
  • 一对多:referencedOn(子实体一侧)、referrersOn(父实体一侧)
  • 多对多:连接表 + via()
  • 使用 with() 预加载关系,避免 N+1 查询

常见问题解答

「Exposed DAO:实体类与关系」课时是免费的吗?

是的 — 「Exposed DAO:实体类与关系」的完整文本可在网页上免费阅读。要进行交互式练习(内置代码编辑器和全天候 AI 导师)并解锁 Kotlin Academy 课程的其余内容,请升级到 CoddyKit PRO。 Kotlin Academy 课程共包含 4 节课。

「Exposed DAO:实体类与关系」这节课中我会学到什么?

使用 DAO API 将表映射为实体类,并浏览实体之间的关系。 你通过在浏览器中直接运行的动手代码来练习 Kotlin Academy,全天候 AI 导师会在你学习这节课的过程中回答你的问题。

学习 Kotlin Academy 需要有经验吗?

无需任何先前经验。CoddyKit 上的 Kotlin Academy 课程适合初学者到高级学习者,你可以从这里开始或从头开始,按照自己的节奏学习。 这是第 4 节课,共 4 节。

「Exposed DAO:实体类与关系」课时需要多长时间?

大多数 CoddyKit 课程大约需要 5–10 分钟。每节课都很精短且互动,所以你能稳步进步,并在网页和应用中从离开的地方继续。

我能在这节 Kotlin Academy 课中编写并运行代码吗?

能。每节 Kotlin Academy 课都包含内置代码编辑器,你可以在浏览器中直接编写并运行真实代码,并获得即时 AI 反馈 — 无需本地设置。

此课程中的所有课时

  1. Exposed 设置:数据库连接与事务 DSL
  2. 使用 Table DSL 定义表
  3. 使用查询 DSL 执行 CRUD:insert、select、update、delete
  4. Exposed DAO:实体类与关系
← 返回 Kotlin Academy