什么是 Exposed,为什么需要它?
Exposed 是 JetBrains 公司为 Kotlin 编程语言开发的一款轻量级但功能强大的 ORM(对象关系映射)库。它提供了两种主要的数据库操作方法:DSL(领域特定语言)和 DAO(数据访问对象)。
为什么需要 Exposed?
- 类型安全:与原始 SQL 查询不同,Exposed 使用 Kotlin 的类型化结构,可以在编译阶段捕获错误。
- 简洁性:使用 Exposed 编写的代码比等效的 SQL 查询或使用 JPA 的 Java 代码更短、更易读。
- 性能:Exposed 不使用反射和代理对象(如 Hibernate),因此速度非常快且可预测。
- 灵活性:您可以在同一个项目中轻松地在 DSL(用于复杂查询)和 DAO(用于简单的 CRUD 操作)之间切换。
- 支持多种数据库:PostgreSQL、MySQL、MariaDB、SQLite、H2、Oracle、SQL Server。
安装 Exposed
Exposed 通过 Gradle 或 Maven 构建系统安装。在您的 build.gradle.kts 中添加以下依赖项:
dependencies { // 核心库 implementation("org.jetbrains.exposed:exposed-core:0.44.1") // 查询 DSL implementation("org.jetbrains.exposed:exposed-dao:0.44.1") // 数据库的 JDBC 驱动(以 PostgreSQL 为例) implementation("org.postgresql:postgresql:42.7.1") // HikariCP 连接池(推荐) implementation("com.zaxxer:HikariCP:5.1.0") // SQL 日志记录(可选) implementation("ch.qos.logback:logback-classic:1.4.14")}对于 Maven(pom.xml):
<dependency> <groupId>org.jetbrains.exposed</groupId> <artifactId>exposed-core</artifactId> <version>0.44.1</version></dependency>快速入门:代码示例
让我们创建一个简单的任务管理(ToDo)应用程序:
import org.jetbrains.exposed.sql.*import org.jetbrains.exposed.sql.transactions.transactionimport org.jetbrains.exposed.sql.SqlExpressionBuilder.eqimport java.time.LocalDateTime
// 1. 定义表object Tasks : Table() { val id = integer("id").autoIncrement() val title = varchar("title", 255) val description = text("description").nullable() val isCompleted = bool("is_completed").default(false) val createdAt = datetime("created_at").default(LocalDateTime.now())
override val primaryKey = PrimaryKey(id)}
// 2. 为方便起见,定义数据类data class Task( val id: Int, val title: String, val description: String?, val isCompleted: Boolean, val createdAt: LocalDateTime)
fun main() { // 3. 连接数据库(以 H2 内存数据库为例) Database.connect("jdbc:h2:mem:test;DB_CLOSE_DELAY=-1", driver = "org.h2.Driver")
transaction { // 4. 创建表 SchemaUtils.create(Tasks)
// 5. 插入数据 val insertId = Tasks.insert { it[title] = "学习 Exposed" it[description] = "阅读文档并编写示例" } get Tasks.id
println("已插入任务,ID:$insertId")
// 6. 查询所有任务 val allTasks = Tasks.selectAll().map { row -> Task( id = row[Tasks.id], title = row[Tasks.title], description = row[Tasks.description], isCompleted = row[Tasks.isCompleted], createdAt = row[Tasks.createdAt] ) } println("所有任务:$allTasks")
// 7. 更新任务 Tasks.updat