ORM для Kotlin: сравнение и примеры
При разработке на Kotlin выбор подходящей ORM (Object-Relational Mapping) — ключевой этап, влияющий на производительность, читаемость кода и удобство поддержки. В этой статье мы сравним три популярных решения: Exposed (официальная библиотека JetBrains), Ktorm (лёгкая DSL-ориентированная ORM) и Hibernate (классический тяжеловес). Разберём их сильные стороны, особенности и приведём рабочие примеры.
1. Exposed — выбор JetBrains
Exposed — это ORM, разработанная специально для Kotlin компанией JetBrains. Она предлагает два подхода: DSL (типобезопасный) и DAO (Data Access Objects). Основное преимущество — полная интеграция с языком: таблицы описываются как объекты Kotlin, запросы проверяются на этапе компиляции.
Пример (DSL-подход):
import org.jetbrains.exposed.sql.*import org.jetbrains.exposed.sql.transactions.transaction
object Users : Table() { val id = integer("id").autoIncrement() val name = varchar("name", 50) val email = varchar("email", 100).uniqueIndex() override val primaryKey = PrimaryKey(id)}
fun main() { Database.connect("jdbc:h2:mem:test", driver = "org.h2.Driver") transaction { SchemaUtils.create(Users) Users.insert { it[name] = "Иван" it[email] = "ivan@example.com" } val result = Users.selectAll().map { "${it[Users.name]} - ${it[Users.email]}" } println(result) // [Иван - ivan@example.com] }}Особенности:
- Типобезопасные запросы (меньше ошибок runtime).
- Нет необходимости в рефлексии (быстрее, чем Hibernate).
- Поддержка миграций через
exposed-migration. - Не требует настройки XML или аннотаций — всё в коде.
2. Ktorm — лёгкость и гибкость
Ktorm — это минималистичная ORM, которая использует Kotlin DSL для построения SQL-запросов. В отличие от Exposed, она не генерирует SQL автоматически, а позволяет писать запросы почти как на чистом SQL, но с проверкой типов.
Пример:
import me.liuwj.ktorm.database.Databaseimport me.liuwj.ktorm.entity.*import me.liuwj.ktorm.schema.*
interface User : Entity<User> { companion object : Entity.Factory<User>() val id: Int val name: String val email: String}
object Users : Table<User>("users") { val id = int("id").primaryKey().bindTo { it.id } val name = varchar("name").bindTo { it.name } val email = varchar("email").bindTo { it.email }}
fun main() { val database = Database.connect("jdbc:h2:mem:test", driver = "org.h2.Driver") database.sequenceOf(Users).toList() // Получить всех пользователей // Вставка: val user = User { name = "Петр" email = "petr@example.com" } database.users.add(user)}Особенности:
- Максимально близок к SQL — легко оптимизировать запросы.
- Небольшой размер JAR (~200 КБ).
- Поддержка расширений:
ktorm-jackson,ktorm-spring-support. - Требует явного связывания полей (bindTo), что увеличивает boilerplate.
3. Hibernate — проверенный стандарт
Hibernate — это мощная, но тяжёлая ORM из мира Java. В Kotlin её используют через аннотации или XML. Hibernate предоставляет полный контроль над кэшированием, ленивой загрузкой и генерацией схемы. Однако из-за рефлексии и прокси-классов возможны проблемы с data class (требуется open).
Пример:
import javax.persistence.*
@Entity@Table(name = "users")data class User( @Id @GeneratedValue(strategy = GenerationType.IDENTITY) val id: Int = 0, @Column(nullable = false) val name: String, @Column(nullable = false, unique = true) val email: String)