[KotlinConf2024] Exploring Exposed: Kotlin’s Database Solution
At KotlinConf2024, Chantal Loncle, a JetBrains Exposed team member, introduced Exposed, an open-source Kotlin library simplifying database access. Since its 2016 debut as a JetBrains internal tool, Exposed has grown into a versatile abstraction layer, supporting multiple databases with type-safe SQL and minimal boilerplate. Chantal guided attendees through configuring connections, defining schemas, manipulating data via DSL, DAO, and plain SQL, and extending functionality with custom features, showcasing Exposed’s flexibility for Kotlin developers.
Why Exposed? Solving Database Pain Points
Exposed addresses common database access challenges, offering a balance between control and abstraction. Chantal explained that developers often need to map Kotlin objects to database records without complex SQL or frameworks requiring annotations. Exposed supports this by providing type-safe interactions, reducing boilerplate, and abstracting database differences. Its cuttlefish mascot reflects its adaptability, enabling database-agnostic apps. Whether needing high-level abstraction or low-level SQL control, Exposed’s consistent API caters to diverse needs, as seen in its growing popularity, ranking sixth among JetBrains’ GitHub repositories.
Setting Up Database Connections
Connecting to a database with Exposed is straightforward yet flexible. Chantal demonstrated the databaseConnect
function, which accepts a connection URL or data source and relies on JDBC drivers. This function doesn’t establish a connection immediately but configures details for later use. Developers can set parameters via a config builder for specific database needs or create multiple connections by storing instances. This approach ensures Exposed handles underlying database variations, allowing developers to focus on application logic rather than connection management.
Transactions: The Heart of Data Operations
Transactions are central to Exposed’s data manipulation. Chantal illustrated how the transaction
function wraps operations like schema creation or data inserts, accepting a database instance or defaulting to a registered one. For multiple connections, developers can set a default database or override settings per transaction. Transactions ensure atomicity, committing or rolling back changes, and Exposed’s transaction manager simplifies resource handling. This design supports both simple and complex workflows, with utility functions like SchemaUtils.create
generating SQL tailored to the target database.
Defining Schemas with Table Objects
Schema definition in Exposed revolves around the Table
class, which maps Kotlin data classes to database tables. Chantal used a docking bay app example, tracking ships and planets. For a Planets
table, developers register columns (e.g., auto-incrementing Long
for IDs, String
for names) and constraints like primary keys. For a Ships
table, a foreign key references Planets
, establishing a one-to-many relationship. Exposed’s SchemaUtils
handles table creation or updates, checking existing schemas to generate necessary SQL, ensuring compatibility across databases like PostgreSQL or MySQL.
Data Manipulation: DSL and DAO Approaches
Exposed offers two data manipulation approaches: domain-specific language (DSL) and data access object (DAO). Chantal showcased DSL’s SQL-like syntax, where extension functions like insert
or selectAll
on table objects build type-safe queries. For example, inserting a ship involves assigning column values, with autogenerated keys accessible post-insertion. The DAO approach, less verbose, maps records to entity classes, abstracting SQL further. Developers call new
on entities instead of insert
, manipulating fields directly. Both methods, switchable via configuration, support complex queries, joins, and updates, catering to different preferences.
Plain SQL and Extensibility
For developers needing direct SQL control, Exposed’s exec
function runs raw SQL strings, as Chantal demonstrated with a stored function to calculate maximum planet distances. Beyond core functionality, Exposed shines in extensibility. Statement interceptors allow custom logic, like logging deletions, at specific lifecycle points. Entity hooks in DAO mode achieve similar customization. Custom column types, such as a PostgreSQL IntRange
for pricing, extend Exposed to unsupported data types. These features, supported by open classes, empower developers to tailor Exposed to unique requirements, enhancing its versatility.
Future of Exposed: Roadmap and Community
Exposed’s roadmap reflects its community-driven evolution, with 43 new contributors in 2023 halving the GitHub issue backlog. Chantal highlighted plans for a stable 1.0 release, improved documentation with tutorials, and migration support via integration with tools like Flyway. IDE tooling will autogenerate table and entity classes, reducing boilerplate, while R2DBC support will enable non-blocking database operations. Community feedback remains vital, as seen in Q&A discussions on migration scripts, ensuring Exposed continues to meet developer needs across diverse applications.