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 反馈 — 无需本地设置。
此课程中的所有课时
- Exposed 设置:数据库连接与事务 DSL
- 使用 Table DSL 定义表
- 使用查询 DSL 执行 CRUD:insert、select、update、delete
- Exposed DAO:实体类与关系