English | 한국어
A hands-on workshop collection for learning the Kotlin Exposed SQL framework step by step. Designed for beginners through advanced users to practice and master the various features of Exposed.
Kotlin Exposed is a Kotlin-specific SQL framework developed by JetBrains. It leverages Kotlin's powerful type system to guarantee SQL query safety at compile time and supports both DSL (Domain Specific Language) and DAO (Data Access Object) styles.
| Feature | Description |
|---|---|
| Type Safety | Catches SQL errors at compile time |
| DSL & DAO | Supports both SQL-style and ORM-style access |
| Coroutines | Full async programming support |
| Lightweight | Lower memory footprint compared to JPA |
| Multi-DB Support | H2, MySQL, PostgreSQL, MariaDB, Oracle, SQL Server |
%%{init: {"theme": "neutral", "themeVariables": {"fontFamily": "'Comic Mono', 'goorm sans code', 'JetBrains Mono', 'goorm sans'"}}}%%
flowchart LR
subgraph API["Exposed API"]
DSL["SQL DSL\nTable.selectAll()\nTable.insert {}"]
DAO["DAO / Entity\nEntity.findById()\nEntity.new {}"]
end
subgraph TX["Transactions"]
JDBC["transaction { }"]
SUSPEND["newSuspendedTransaction { }"]
end
subgraph DB["Databases"]
H2["H2"]
PG["PostgreSQL"]
MY["MySQL"]
MA["MariaDB"]
end
DSL --> JDBC
DSL --> SUSPEND
DAO --> JDBC
DAO --> SUSPEND
JDBC --> H2 & PG & MY & MA
SUSPEND --> H2 & PG & MY & MA
classDef api fill:#E3F2FD,stroke:#90CAF9,color:#1565C0
classDef tx fill:#E8F5E9,stroke:#A5D6A7,color:#2E7D32
classDef db fill:#FFF3E0,stroke:#FFCC80,color:#E65100
class DSL,DAO api
class JDBC,SUSPEND tx
class H2,PG,MY,MA db
| Technology | Version |
|---|---|
| Kotlin | 2.3.20 |
| Java | 21 |
| Exposed | 1.1.1 |
| Spring Boot | 3.5.11 |
| Kotlinx Coroutines | 1.10.2 |
| Bluetape4k | 1.6.0 |
| Gradle Wrapper | 9.4.1 |
The recommended learning order for this workshop:
- Basics: Spring Boot + Exposed integration
- Alternatives: Comparing JPA alternatives
- Exposed Basics: DSL and DAO patterns
- DDL/DML: Schema definition and data manipulation
- Advanced: Encryption, JSON, custom types
- JPA Migration: Converting JPA code to Exposed
- Async: Coroutines, Virtual Threads
- Spring Integration: Transactions, cache, repository patterns
- Multi-Tenancy: Multi-tenant architecture
- High Performance: Cache strategies, routing datasource
%%{init: {"theme": "neutral", "themeVariables": {"fontFamily": "'Comic Mono', 'goorm sans code', 'JetBrains Mono', 'goorm sans'"}}}%%
flowchart TD
START(["Start"])
subgraph Basics["Basics"]
S01["01 Spring Boot\n+ Exposed"]
S02["02 JPA Alternatives\nComparison"]
S03["03 Exposed Basics\nDSL & DAO"]
end
subgraph Core["Core"]
S04["04 DDL\nSchema Definition"]
S05["05 DML\nData Manipulation"]
S06["06 Advanced\nEncryption / JSON / Custom"]
end
subgraph Migration["Migration"]
S07["07 JPA → Exposed\nConversion Patterns"]
end
subgraph Async["Async & Integration"]
S08["08 Coroutines\n& Virtual Threads"]
S09["09 Spring Integration\nTx / Cache / Repo"]
end
subgraph Production["Production-Ready"]
S10["10 Multi-Tenancy\nSchema Isolation"]
S11["11 High Performance\nCache / Routing / Bench"]
end
START --> S01 --> S02 --> S03
S03 --> S04 --> S05 --> S06
S06 --> S07
S06 --> S08
S07 --> S08
S08 --> S09
S09 --> S10 --> S11
classDef startEnd fill:#F3E5F5,stroke:#CE93D8,color:#6A1B9A,font-weight:bold
classDef basics fill:#E3F2FD,stroke:#90CAF9,color:#1565C0
classDef core fill:#E8F5E9,stroke:#A5D6A7,color:#2E7D32
classDef migration fill:#FFFDE7,stroke:#FFF176,color:#F57F17
classDef async fill:#FFF3E0,stroke:#FFCC80,color:#E65100
classDef production fill:#FCE4EC,stroke:#F48FB1,color:#AD1457
class START startEnd
class S01,S02,S03 basics
class S04,S05,S06 core
class S07 migration
class S08,S09 async
class S10,S11 production
Full explanations for all examples are available at Kotlin Exposed Book.
%%{init: {"theme": "neutral", "themeVariables": {"fontFamily": "'Comic Mono', 'goorm sans code', 'JetBrains Mono', 'goorm sans'"}}}%%
flowchart TB
subgraph Shared["00 Shared Infrastructure"]
EST["exposed-shared-tests\nTest Utilities"]
end
subgraph SpringBoot["01 Spring Boot"]
MVC["Spring MVC\n+ Virtual Threads"]
WF["Spring WebFlux\n+ Coroutines"]
end
subgraph Alt["02 JPA Alternatives"]
HIB["Hibernate\nReactive"]
R2["R2DBC"]
VX["Vert.x\nSQL Client"]
end
subgraph Basic["03 Exposed Basics"]
DSLEX["SQL DSL"]
DAOEX["DAO Entity"]
end
subgraph DDL["04 DDL"]
CONN["Connection"]
SCH["Schema DDL"]
end
subgraph DML["05 DML"]
CRUD["DML Basics"]
TYPE["Column Types"]
FUNC["SQL Functions"]
TXN["Transactions"]
ENT["Entity API"]
end
subgraph Adv["06 Advanced"]
CRYPT["Encryption"]
JSON["JSON"]
CUSTOM["Custom Columns\n& Entities"]
DT["Date / Time"]
end
subgraph JPA["07 JPA Migration"]
JPAB["JPA Basic"]
JPAA["JPA Advanced"]
end
subgraph Async["08 Async"]
CORO["Coroutines"]
VT["Virtual Threads"]
end
subgraph Spring["09 Spring Integration"]
AUTO["AutoConfig"]
TXMGR["Tx Management"]
REPO["Repository"]
CACHE["Cache"]
end
subgraph MT["10 Multi-Tenancy"]
MTW["Web"]
MTVT["Web + VT"]
MTWF["WebFlux"]
end
subgraph Perf["11 High Performance"]
CS["Cache Strategies"]
RDS["Routing DS"]
BENCH["Benchmark"]
end
EST -.-> SpringBoot & Basic & DDL & DML & Adv & JPA & Async & Spring & MT & Perf
Basic --> DDL --> DML --> Adv
Adv --> JPA & Async
Async --> Spring --> MT --> Perf
classDef shared fill:#E0F2F1,stroke:#80CBC4,color:#00695C
classDef spring fill:#E3F2FD,stroke:#90CAF9,color:#1565C0
classDef alt fill:#FFFDE7,stroke:#FFF176,color:#F57F17
classDef basic fill:#E8F5E9,stroke:#A5D6A7,color:#2E7D32
classDef ddl fill:#F3E5F5,stroke:#CE93D8,color:#6A1B9A
classDef dml fill:#E8F5E9,stroke:#A5D6A7,color:#2E7D32
classDef adv fill:#FFF3E0,stroke:#FFCC80,color:#E65100
classDef jpa fill:#FFFDE7,stroke:#FFF176,color:#F57F17
classDef async fill:#FCE4EC,stroke:#F48FB1,color:#AD1457
classDef springInt fill:#E3F2FD,stroke:#90CAF9,color:#1565C0
classDef mt fill:#F3E5F5,stroke:#CE93D8,color:#6A1B9A
classDef perf fill:#FFEBEE,stroke:#EF9A9A,color:#C62828
class EST shared
class MVC,WF spring
class HIB,R2,VX alt
class DSLEX,DAOEX basic
class CONN,SCH ddl
class CRUD,TYPE,FUNC,TXN,ENT dml
class CRYPT,JSON,CUSTOM,DT adv
class JPAB,JPAA jpa
class CORO,VT async
class AUTO,TXMGR,REPO,CACHE springInt
class MTW,MTVT,MTWF mt
class CS,RDS,BENCH perf
Provides common test utilities and resources used across the entire exposed-workshop project. Supports consistent testing across different database environments.
Learn how to build synchronous REST APIs using Spring MVC + Virtual Threads + Exposed. Practice many-to-many relationship mapping with movie and actor data.
Learn how to build asynchronous REST APIs using Spring WebFlux + Kotlin Coroutines + Exposed. Master the integration between reactive programming and Exposed.
Example of building a reactive Spring Boot application using Hibernate Reactive.
Example of reactive database access using Spring Data R2DBC.
Example of event-driven asynchronous database operations using Vert.x SQL Client.
Learn the Exposed DAO (Data Access Object) pattern. Master object-oriented database operations using Entity and EntityClass.
Learn the Exposed SQL DSL (Domain Specific Language). Master type-safe SQL query construction and DSL benefits.
Learn core concepts of connection management including database connection setup, exception handling, timeouts, and connection pooling.
Learn Exposed DDL features. Master table, column, index, and sequence definitions.
Learn basic SELECT, INSERT, UPDATE, DELETE patterns. Practice conditions, subqueries, paging, Batch Insert/Update, CTE (Common Table Expression), and other common production patterns.
Learn the various column types provided by Exposed. Covers basic types through arrays, BLOB, UUID, and unsigned integers.
Learn how to use various SQL functions in Exposed queries. Covers aggregate functions, window functions, math/trigonometric functions, and more.
Learn Exposed transaction management features. Covers isolation levels, nested transactions, rollback, and coroutine integration.
Learn the powerful Exposed Entity API. Covers various primary key strategies, relationship mapping, lifecycle hooks, and caching.
Learn how to transparently encrypt/decrypt database columns using the exposed-crypt extension.
Learn how to integrate Java 8's java.time API with Exposed.
Learn how to integrate the kotlinx.datetime library with Exposed. Ideal for multiplatform projects.
Learn how to work with JSON/JSONB columns using the exposed-json module.
Learn how to safely handle monetary values using the exposed-money module.
Learn how to implement custom column types. Build transparent transformations for encryption, compression (GZIP/LZ4/Snappy/ZSTD), and serialization (Kryo/Fury).
Implement custom entities with various ID generation strategies including Snowflake, KSUID, Time-based UUID, and Base62 encoded UUID.
Learn how to process JSON/JSONB columns using the Jackson library.
Learn how to process JSON columns using the Alibaba Fastjson2 library.
Learn how to implement searchable (deterministic) encryption using Jasypt.
Learn how to process JSON/JSONB columns using Jackson 3.x.
Learn how to encrypt column data using AEAD (non-deterministic) and DAEAD (deterministic) modes with the Google Tink library. DAEAD mode allows WHERE clause searches on encrypted data.
Learn how to implement JPA basic features with Exposed. Covers Entity, relationships (One-to-One, One-to-Many, Many-to-Many), primary keys, and composite keys.
Learn how to implement JPA advanced features with Exposed. Covers inheritance mapping (Single Table, Table Per Class, Joined Table), Self-Reference, Auditable, and optimistic locking.
Learn how to use Exposed in a Kotlin Coroutines environment. Covers newSuspendedTransaction, suspendedTransactionAsync, and more.
Learn how to use Exposed with Java 21 Virtual Threads. Achieve high-performance async processing while maintaining a blocking code style.
Learn how to configure Exposed using Spring Boot auto-configuration.
Learn how to manage programmatic transactions with Spring's TransactionTemplate.
Learn how to manage declarative transactions with the @Transactional annotation.
Learn how to implement Exposed repositories using the Spring Data Repository pattern.
Implement asynchronous data access using the Repository pattern in a coroutine environment.
Learn how to use Spring Boot Cache with Exposed.
Learn how to use Lettuce-based Suspended Cache with Exposed in a coroutine environment.
Learn how to implement schema-based multi-tenancy in a Spring Web application.
Learn how to implement multi-tenancy in a Virtual Threads environment.
Learn how to implement reactive multi-tenancy using WebFlux and Coroutines.
Implement various cache strategies (Read Through, Write Through, Write Behind) with Redisson + Exposed.
Implement asynchronous cache strategies in a coroutine environment.
Learn flexible DataSource routing configuration for multi-tenant or read replica architectures.
Measure performance of cache/routing examples using kotlinx-benchmark micro-benchmarks. Provides smoke and main profiles with Markdown report generation.
- JDK 21 or higher (for Virtual Threads and Preview features)
- Gradle Wrapper 9.4.1 included (use
./gradlew) - Docker (for Testcontainers)
# Quick local verification (H2 only)
./gradlew test -PuseFastDB=true
# Full project build and test
./gradlew clean build
# Run tests for a specific module
./gradlew :03-routing-datasource:test
./gradlew :01-dml:test
./gradlew :spring-mvc-exposed:testThe root settings.gradle.kts generates the Gradle project path from the leaf directory name. If paths are confusing, check with ./gradlew projects.
By default, tests run against H2, PostgreSQL, MySQL V8. Use Gradle properties to control the test scope.
# Test with H2 only (fast local development)
./gradlew test -PuseFastDB=true
# Test with specific databases
./gradlew test -PuseDB=H2,POSTGRESQL
./gradlew test -PuseDB=H2,POSTGRESQL,MYSQL_V8,MARIADB
# Test with defaults (H2 + PostgreSQL + MySQL V8)
./gradlew testAvailable -PuseDB values (TestDB enum names):
| Value | Description |
|---|---|
H2 |
H2 (in-memory, default mode) |
H2_V1 |
H2 1.x compatibility mode |
H2_MYSQL |
H2 (MySQL compatibility mode) |
H2_MARIADB |
H2 (MariaDB compatibility mode) |
H2_PSQL |
H2 (PostgreSQL compatibility mode) |
MARIADB |
MariaDB (Testcontainers) |
MYSQL_V5 |
MySQL 5.x (Testcontainers) |
MYSQL_V8 |
MySQL 8.x (Testcontainers) |
POSTGRESQL |
PostgreSQL (Testcontainers) |
POSTGRESQLNG |
PostgreSQL NG driver |
COCKROACH |
Note
Priority: -PuseDB > -PuseFastDB > default (H2, POSTGRESQL, MYSQL_V8)
- Use the included Gradle Wrapper (
./gradlew). - Opening in IntelliJ IDEA automatically recognizes all multi-modules.
- With Docker, you can run Testcontainers-based PostgreSQL/MySQL/Redis tests directly.
This project is designed for learning purposes. All contributions including typo fixes, example additions, and translation improvements are welcome.
Apache License 2.0
