Представь: ты пишешь микросервис на Ktor, всё летает на корутинах, код минималистичный и всё прекрасно... До того момента, когда ты касаешься базы данных. Все мечты разбиваются об Spring Data и Koin, либо об тонны бойлерплейта на Exposed или Ktorm DSL. Знакомо?

У меня есть решение: KRepo — это лёгкий, полностью suspend-ориентированный слой репозиториев, который даёт вам магию Spring Data (интерфейсы, findBy…, CRUD из коробки), но без DI-контейнеров, без рефлексии в рантайме и тонн мусора.

interface UserRepository : Repository<User, Long> {
    suspend fun findByEmail(email: String): User?
    suspend fun findByAgeGreaterThan(age: Int): List<User>
}

— и всё. Никаких имплементаций или инъекций. Под капотом — динамический прокси, кэширование метаданных и независимость от фреймворков: плагины под Exposed, JDBC или MongoDB реализуются отдельно.

Как и какие пробелы закрывает моё детище

  1. Blocking I/O и отсутствие suspend-поддержки из коробки:

    • Exposed/JDBC — синхронные по умолчанию, нужно вручную оборачивать в withContext(Dispatchers.IO), что приводит к контекст-свитчингу и снижению производительности в Ktor. Spring Data JPA — чисто blocking.

    • У KRepo 100% приостанавливаемая реализация CRUD и кастомные методы через динамические прокси. Все операции — suspend fun, интегрируются напрямую в корутины Ktor без обёрток.

    • Это идеально подходит для async-роутов Ktor: нет "пробок", выше пропускная способность под нагрузкой. Закрывает потребность в reactive Spring (R2DBC) и/или бойлерплейта.

  2. Тяжёлый DI и автоконфигурация:

    • Spring Data требует Spring Boot/Koin для инъекции репозиториев — overhead для легковесного Ktor. В Exposed — ручная регистрация в DI, без "магии".

    • В KRepo RepositoryContext — простой registry. Нет Spring/Koin. Репозитории генерируются на лету через фабрики (RepositoryFactory).

    • Легче тестировать (мокаешь DataAccessor) и деплойить (меньше зависимостей).

  3. Boilerplate-код для репозиториев:

    • В Exposed/Ktorm — пишешь SQL/DSL вручную для каждого метода. Нет динамического парсинга имён методов (типа findByName).

    • Proxy-based генерация без ручной имплементации. Определяешь интерфейс, прокси сам реализует через DataAccessor.

    • Экономит часы на CRUD: пишешь интерфейс — и готово.

  4. Жёсткая привязка к одному ORM/БД:

    • Абстрактный интерфейс для любого бэкенда (Exposed, MongoDB, JDBC, in-memory). Модули реализации для Exposed, чистого SQL, MongoDB можно создавать самому.

  5. Runtime-overhead из-за рефлексии:

    • Метаданные (методы, entity-структура) собираются один раз на compile-time/reflection-at-startup и кэшируются.

  6. Отсутствие "Spring-like" удобства в Ktor:

    • Spring Data-подобный API, но Ktor-native. Интерфейсы с suspend-методами, автоматическая генерация. Интеграция в Ktor: просто регистрируешь в контексте и используешь в роутах.

  7. Сложности с кастомными запросами и пагинацией:

    • Поддержка кастомных suspend-методов через прокси. findByAgeGreaterThan → автоматический запрос. Легче масштабировать на сложные запросы без потери асинхронности.

Состояние проекта и ссылки

На данный момент полностью реализован core-модуль со всей необходимой абстракцией (методы, парсеры, прокси, аннотации и т.д). Осталась только реализация паттерна для конкретных БД и драйверов: SQL-диалекты, Mongo и in-memory.

Структура сейчас:

./core/src/main/kotlin
├── exception
│   ├── QueryParseException.kt
│   └── RepositoryException.kt
├── query
│   ├── LogicalOperator.kt
│   ├── MethodNameParser.kt
│   ├── Operator.kt
│   ├── ParsedMethod.kt
│   ├── QueryAction.kt
│   ├── QueryBuilder.kt
│   └── QueryCondition.kt
├── repository
│   ├── access
│   │   └── DataAccessor.kt
│   ├── annotations
│   │   ├── Column.kt
│   │   ├── Entity.kt
│   │   ├── Id.kt
│   │   └── Transient.kt
│   ├── CrudRepositoryDelegate.kt
│   ├── CrudRepository.kt
│   ├── DefaultRepositoryFactory.kt
│   ├── KtorRepository.kt
│   ├── metadata
│   │   ├── ColumnProperty.kt
│   │   ├── EntityColumn.kt
│   │   ├── EntityMetadata.kt
│   │   └── PropertyExtensions.kt
│   ├── RepositoryConfig.kt
│   ├── RepositoryContext.kt
│   ├── RepositoryFactory.kt
│   ├── RepositoryInvocationHandler.kt
│   ├── RepositoryMetadata.kt
│   └── RepositoryMethod.kt
└── utils
    └── ReflectionUtils.kt

Ссылки и контакты:

На этом всё, ждите новостей!

Комментарии (0)