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.Database
import 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, length = 50)
val name: String = "",
@Column(unique = true, length = 100)
val email: String = ""
)
fun main() {
val sessionFactory = // стандартная конфигурация Hibernate
val session = sessionFactory.openSession()
session.beginTransaction()
session.save(User(name = "Анна", email = "anna@example.com"))
session.transaction.commit()
val users = session.createQuery("from User", User::class.java).list()
println(users)
}
Особенности:
- Богатая экосистема: кэ
Также в библиотеке
Puppeteer для JavaScript (Node.js): полное руководство с примерами
JWT токены в PHP: библиотека firebase/php-jwt и полное руководство
OAuth клиент для C# (.NET): библиотека IdentityModel и интеграция с OAuth 2.0
Redis клиент для C# (.NET): StackExchange.Redis