SQL is not a problem to be solved - it's a powerful tool to be embraced.
This is the philosophy behind Kapper...
Kapper is a lightweight, Dapper-inspired ORM (Object-Relational Mapping) library written in Kotlin, targeting the JVM ecosystem. It embraces SQL rather than abstracting it away, providing a simple, intuitive API for executing queries and mapping results.
See Kapper for more information.
Instead of adding another abstraction layer, Kapper embraces three core principles:
-
SQL is the Best Query Language: SQL has evolved over decades to be expressive, powerful, and optimised for database operations. Instead of hiding it, we should leverage it directly.
-
Minimal Abstraction: Kapper provides just enough abstraction to make database operations comfortable in Kotlin, without trying to reinvent database interactions. Kapper prefers extension of existing APIs rather than abstraction of them.
-
Transparency: What you write is what gets executed. There's no magic query generation or hidden database calls.
📖 Read more about Kapper's philosophy
- 🎯 SQL-First Approach: Write your SQL directly - no DSL or query builders
- ⚡ High Performance: Near-JDBC performance with automatic object mapping
- 🏗️ Auto-Mapping: Automatically map result sets to Kotlin data classes and Java records
- 🔧 Custom Mappers: Full control with manual mapping for performance-critical paths
- 🚀 Coroutines Support: First-class support for Kotlin coroutines with
kapper-coroutines - 🌊 Flow Integration: Return query results as Kotlin
Flowfor reactive programming - 📦 Java Records: Native support for Java record classes alongside Kotlin data classes
- 🔄 Transactions: Simple transaction handling with automatic commit/rollback
- 📊 Bulk Operations: Efficient batch inserts, updates, and deletes with
executeAll - 🗄️ Database Support: PostgreSQL, MySQL, SQLite, Oracle, MS SQL Server, and many others
- 📏 Minimal Dependencies: Lightweight library with zero external dependencies
- 🔌 JDBC Extension: Extends
java.sql.Connection- works alongside existing JDBC code
📖 Explore all features in detail
data class User(val id: UUID, val name: String, val email: String?)
// Simple query
val users = connection.query<User>("SELECT * FROM users WHERE age > :age", "age" to 18)
// Insert data
connection.execute(
"INSERT INTO users(id, name, email) VALUES(:id, :name, :email)",
"id" to UUID.randomUUID(),
"name" to "Alice",
"email" to "alice@example.com"
)Kapper consistently outperforms other ORMs while maintaining the simplicity and transparency of SQL.
Discover everything Kapper can do for your project! Visit our comprehensive documentation site:
- 🚀 Quick Start Guide - Get up and running in minutes
- 📖 User Guide - Complete feature coverage with examples
- 💻 Working Examples - Real-world patterns and best practices
- ⚡ Performance Benchmarks - See how Kapper compares to other ORMs
- 🔧 Installation Guide - Maven, Gradle, and dependency setup
- 🔄 Migration Guide - Migrating from other ORMs
- 📚 API Reference - Complete API documentation
Special thanks to the kind people from YourKit for supporting open source projects and providing us with licenses for their profilers.
YourKit is the creator of YourKit Java Profiler, YourKit .NET Profiler,
We welcome contributions! Please see our documentation site for guides and examples, or feel free to open an issue or submit a pull request.
Kapper is released under the Apache 2.0 License.


