Skip to content
This repository was archived by the owner on Apr 19, 2024. It is now read-only.

Repository files navigation

Beak

ConcourseDownload

Beak is a functional Kotlin SQL DSL. It provides a type-safe, exception-free data access layer. Beak builds upon JetBrains' Exposed Kotlin SQL DSL library and the Arrow Kotlin functional programming library.

Alpha Release Considerations

Beak is in early stages of development and is released as alpha software. All aspects of the API are subject to change until our first release.

Currently, Beak is built as extension functions on top of the Exposed library's DAO layer. Beak may remove Exposed as a dependency which would significantly change the API.

Currently, Beak supports H2 and MySQL. We plan to support more databases in the future.

Installation

Add Beak's Maven repository to your build configuration:

https://dl.bintray.com/codebandits/beak

Find example dependency configurations for the latest version here:

Download

Usage

Here is a simple example comparing Exposed's .new {} with Beak's .newOrError {}:

importarrow.core.Eitherimportarrow.core.flatMapimportio.github.codebandits.beak.DataAccessErrorimportio.github.codebandits.beak.beakTransactionimportio.github.codebandits.beak.newOrErrorimportio.github.codebandits.beak.updateByIdOrErrorimportorg.jetbrains.exposed.dao.EntityIDimportorg.jetbrains.exposed.dao.LongEntityimportorg.jetbrains.exposed.dao.LongEntityClassimportorg.jetbrains.exposed.dao.LongIdTableimportorg.jetbrains.exposed.sql.Databaseimportorg.jetbrains.exposed.sql.SchemaUtils.createimportorg.jetbrains.exposed.sql.transactions.transaction// Setup table objects and entity classes using Exposed's API:object FeatherTable : LongIdTable("feathers") {
val type = varchar("type", 255)
}
classFeatherEntity(id:EntityID<Long>) : LongEntity(id) {
companionobject:LongEntityClass<FeatherEntity>(FeatherTable)
var type by FeatherTable.type
}
funmain(args:Array<String>) {
Database.connect("jdbc:h2:mem:test;DB_CLOSE_DELAY=-1", driver ="org.h2.Driver")
transaction { create(FeatherTable) }
// Create a new Feather using Exposed's API.// This will throw exceptions when errors are encountered.val feather1:FeatherEntity= transaction {
FeatherEntity.new {
type ="contour"
}
}
// Create a new Feather using Beak's API.// This will return a DataAccessError when errors are encountered.val feather2Result:Either<DataAccessError, FeatherEntity> =FeatherEntity.newOrError {
type ="down"
}
// Combine multiple operations in one transaction to link rollbacks for all the data access operations.// When the second operations fails the first operation will also be rolled back, returning a DataAccessError.val feather3Result:Either<DataAccessError, FeatherEntity> = beakTransaction {
FeatherEntity.newOrError { type ="down" }
.flatMap { featherEntity ->FeatherEntity.updateByIdOrError(featherEntity.id.value) { type ="x".repeat(500) }
}
}
when (feather3Result) {
isEither.Right->println("operation succeeded: ${feather3Result.b}")
isEither.Left->println("operation failed: ${feather3Result.a}") // This one prints
}
}

Error Handling

Beak's data access functions endeavor to never throw exceptions. Instead, they return an Either data type with a DataAccessError as the left hand side. DataAccessError is a sealed class hierarchy of all possible data access errors so you can use functional patterns to efficiently handle all data access failures in your application.

See Railway Oriented Programming for more insight into this error handling approach.

About

a functional Kotlin SQL DSL

Topics

Resources

Stars

6 stars

Watchers

3 watching

Forks

Releases

Packages

Contributors

Languages