alexeybrod / spring-kotlin-exposed

playground for spring-boot 2.*, kotlin , jetbrains-exposed, postgres, jsonb, flyway, docker

Geek Repo:Geek Repo

Github PK Tool:Github PK Tool

spring-kotlin-exposed

playground for spring-boot 2.*, kotlin, jetbrains-exposed, postgres, jsonb, flyway, docker

  • Yes, we can talk to a sql db. It's easy. No rocket science.
  • There is a life besides the "dark art of hibernate / jpa".
  • Alternatives: JDBI, Requery, rxjava-jdbc, Jooq, Querydsl ...

jetbrains exposed (overview)

  • wiki: https://github.com/JetBrains/Exposed/wiki
  • flavours:
    • DSL Api: typesafe sql (immutable data structures)
    • DAO Api: ORM-/ActiveRecord-style (mutable entities)
  • highlights:
    • integrates with spring transaction manager
    • works with flyway db migrations
    • supports multiple datasources within one application (e.g.: source-db-1, source-db2, sink-db)
    • speeds up startup of spring-boot
    • low memory footprint (playground runs on 256M)
    • precise and typesafe sql queries (WYSISWG)
    • no runtime reflection magic
    • writing add-ons is simple, e.g. custom db-column-types

Exposed DSL Api: examples

  • It's easy. No ORM magic. WYSIWYG.
  • Ready for starship java "enterprise" deployments.
    # The beauty of exposed-dsl... Simple. Readable. Typesafe.
    
    # Example: query db
 
    fun findAllBooksJoinAuthor() =
            (AuthorTable innerJoin BookTable)
                    .selectAll()
                    .map { 
                        BookRecordJoinAuthorRecord(
                            bookRecord = it.toBookRecord(), 
                            authorRecord = it.toAuthorRecord()
                        ) 
                    }
    
    # Example: db schema 
    
    object AuthorTable : Table("author") {
        val id = uuid("id").primaryKey()
        val createdAt = instant("created_at")
        val modifiedAt = instant("updated_at")
        val version = integer("version")
        val name = text("name")
    }
                    
    object BookTable : Table("book") {
        val id = uuid("id").primaryKey()
        val createdAt = instant("created_at")
        val modifiedAt = instant("updated_at")
        val version = integer("version")
        val authorId = (uuid("author_id") references AuthorTable.id)
        val title = varchar("title", 255)
        val status = enumerationByName("status", 255, BookStatus::class.java)
        val price = decimal("price", 15, 2)
    } 
    
    # Example: Table Record Structures as immutable data classes
    
    data class AuthorRecord(
            val id: UUID,
            val createdAt: Instant,
            val modifiedAt: Instant,
            val version: Int,
            val name: String
    )   
    
    data class BookRecord(
            val id: UUID,
            val createdAt: Instant,
            val modifiedAt: Instant,
            val version: Int,
            val authorId: UUID,
            val title: String,
            val status: BookStatus,
            val price: BigDecimal
    )            

playground

    # build db + app and start everything using docker-compose
     
    $ make -C rest-api playground.up
    
    browse to: http://localhost:8080/swagger-ui.html

build

    $ make -C rest-api app.build

run local db (docker)

    $ make -C rest-api db-local.up

examples:

  • api tweeter: simple crud (tables: tweet).
# Highlights: postgres enum types
 
sql ..
 
CREATE TYPE TweetStatusType AS ENUM ('DRAFT', 'PENDING', 'PUBLISHED');

CREATE TABLE Tweet (
  (...)
  status TweetStatusType NOT NULL DEFAULT 'DRAFT'
);
 
kotlin ...
 
object TweetsTable : Table("tweet") {
    (...)
    val status = enumerationByNameAndSqlType(
            name = "status", sqlType = "TweetStatusType", klass = TweetStatus::class.java
    )
}

  • api bookstore: crud-ish (joined tables: author, book)
  • api bookz: jsonb examples (tables: bookz)

This example project is based on ...

Whats wrong with orm, jpa, hibernate and in-memory h2-db these days ?

There is no silver bullet. It's born in a world of single-instance big fat application servers. It hardly fits into a modern world of:

  • functional programming: e.g. immutable threadsafe pojos / data classes
  • CQRS and eventsourcing
  • horizontal scaling of polyglot microservices

Make up your mind ...

About

playground for spring-boot 2.*, kotlin , jetbrains-exposed, postgres, jsonb, flyway, docker


Languages

Language:Kotlin 90.6%Language:Makefile 5.7%Language:Shell 3.0%Language:Dockerfile 0.7%