Are you happy with your logging solution? Would you help us out by taking a 30-second survey? Click here

Exposed

Kotlin SQL Framework

Star full 4f7b624809470f25b6493d5a7b30d9b9cb905931146e785d67c86ef0c205a402Star full 4f7b624809470f25b6493d5a7b30d9b9cb905931146e785d67c86ef0c205a402Star full 4f7b624809470f25b6493d5a7b30d9b9cb905931146e785d67c86ef0c205a402Star blank 374f33e4d622a2930833db3cbea26b5d03dc44961a6ecab0b9e13276d97d6682Star blank 374f33e4d622a2930833db3cbea26b5d03dc44961a6ecab0b9e13276d97d6682 (1 ratings)
Rated 3.0 out of 5
Subscribe to updates I use Exposed


Statistics on Exposed

Number of watchers on Github 1257
Number of open issues 64
Average time to close an issue about 2 months
Main language Kotlin
Average time to merge a PR 1 day
Open pull requests 11+
Closed pull requests 10+
Last commit over 1 year ago
Repo Created over 6 years ago
Repo Last Updated over 1 year ago
Size 10.4 MB
Organization / Authorjetbrains
Contributors10
Page Updated
Do you use Exposed? Leave a review!
View open issues (64)
View Exposed activity
View on github
Fresh, new opensource launches 🚀🚀🚀
Trendy new open source projects in your inbox! View examples

Subscribe to our mailing list

Evaluating Exposed for your project? Score Explanation
Commits Score (?)
Issues & PR Score (?)

JetBrains team project TC Build status Download GitHub License

Exposed - Kotlin SQL Library

Exposed is a prototype for a lightweight SQL library written over JDBC driver for Kotlin language. It does have two layers of database access: typesafe SQL wrapping DSL and lightweight data access objects

Exposed is currently available for maven/gradle builds at https://bintray.com/kotlin/exposed/exposed/view#

Dialects

Currently supported database dialects:

SQL DSL sample:

import org.jetbrains.exposed.sql.*
import org.jetbrains.exposed.sql.transactions.transaction
import org.jetbrains.exposed.sql.SchemaUtils.create
import org.jetbrains.exposed.sql.SchemaUtils.drop

object Users : Table() {
    val id = varchar("id", 10).primaryKey() // Column<String>
    val name = varchar("name", length = 50) // Column<String>
    val cityId = (integer("city_id") references Cities.id).nullable() // Column<Int?>
}

object Cities : Table() {
    val id = integer("id").autoIncrement().primaryKey() // Column<Int>
    val name = varchar("name", 50) // Column<String>
}

fun main(args: Array<String>) {
    Database.connect("jdbc:h2:mem:test", driver = "org.h2.Driver")

    transaction {
        create (Cities, Users)

        val saintPetersburgId = Cities.insert {
            it[name] = "St. Petersburg"
        } get Cities.id

        val munichId = Cities.insert {
            it[name] = "Munich"
        } get Cities.id

        Cities.insert {
            it[name] = "Prague"
        }

        Users.insert {
            it[id] = "andrey"
            it[name] = "Andrey"
            it[cityId] = saintPetersburgId
        }

        Users.insert {
            it[id] = "sergey"
            it[name] = "Sergey"
            it[cityId] = munichId
        }

        Users.insert {
            it[id] = "eugene"
            it[name] = "Eugene"
            it[cityId] = munichId
        }

        Users.insert {
            it[id] = "alex"
            it[name] = "Alex"
            it[cityId] = null
        }

        Users.insert {
            it[id] = "smth"
            it[name] = "Something"
            it[cityId] = null
        }

        Users.update({Users.id eq "alex"}) {
            it[name] = "Alexey"
        }

        Users.deleteWhere{Users.name like "%thing"}

        println("All cities:")

        for (city in Cities.selectAll()) {
            println("${city[Cities.id]}: ${city[Cities.name]}")
        }

        println("Manual join:")
        (Users innerJoin Cities).slice(Users.name, Cities.name).
            select {(Users.id.eq("andrey") or Users.name.eq("Sergey")) and
                    Users.id.eq("sergey") and Users.cityId.eq(Cities.id)}.forEach {
            println("${it[Users.name]} lives in ${it[Cities.name]}")
        }

        println("Join with foreign key:")


        (Users innerJoin Cities).slice(Users.name, Users.cityId, Cities.name).
                select {Cities.name.eq("St. Petersburg") or Users.cityId.isNull()}.forEach {
            if (it[Users.cityId] != null) {
                println("${it[Users.name]} lives in ${it[Cities.name]}")
            }
            else {
                println("${it[Users.name]} lives nowhere")
            }
        }

        println("Functions and group by:")

        ((Cities innerJoin Users).slice(Cities.name, Users.id.count()).selectAll().groupBy(Cities.name)).forEach {
            val cityName = it[Cities.name]
            val userCount = it[Users.id.count()]

            if (userCount > 0) {
                println("$userCount user(s) live(s) in $cityName")
            } else {
                println("Nobody lives in $cityName")
            }
        }

        drop (Users, Cities)

    }
}

Outputs:

    SQL: CREATE TABLE IF NOT EXISTS Cities (id INT AUTO_INCREMENT NOT NULL, name VARCHAR(50) NOT NULL, CONSTRAINT pk_Cities PRIMARY KEY (id))
    SQL: CREATE TABLE IF NOT EXISTS Users (id VARCHAR(10) NOT NULL, name VARCHAR(50) NOT NULL, city_id INT NULL, CONSTRAINT pk_Users PRIMARY KEY (id))
    SQL: ALTER TABLE Users ADD FOREIGN KEY (city_id) REFERENCES Cities(id)
    SQL: INSERT INTO Cities (name) VALUES ('St. Petersburg')
    SQL: INSERT INTO Cities (name) VALUES ('Munich')
    SQL: INSERT INTO Cities (name) VALUES ('Prague')
    SQL: INSERT INTO Users (id, name, city_id) VALUES ('andrey', 'Andrey', 1)
    SQL: INSERT INTO Users (id, name, city_id) VALUES ('sergey', 'Sergey', 2)
    SQL: INSERT INTO Users (id, name, city_id) VALUES ('eugene', 'Eugene', 2)
    SQL: INSERT INTO Users (id, name, city_id) VALUES ('alex', 'Alex', NULL)
    SQL: INSERT INTO Users (id, name, city_id) VALUES ('smth', 'Something', NULL)
    SQL: UPDATE Users SET name='Alexey' WHERE Users.id = 'alex'
    SQL: DELETE FROM Users WHERE Users.name LIKE '%thing'
    All cities:
    SQL: SELECT Cities.id, Cities.name FROM Cities
    1: St. Petersburg
    2: Munich
    3: Prague
    Manual join:
    SQL: SELECT Users.name, Cities.name FROM Users INNER JOIN Cities ON Cities.id = Users.city_id WHERE ((Users.id = 'andrey') or (Users.name = 'Sergey')) and Users.id = 'sergey' and Users.city_id = Cities.id
    Sergey lives in Munich
    Join with foreign key:
    SQL: SELECT Users.name, Users.city_id, Cities.name FROM Users INNER JOIN Cities ON Cities.id = Users.city_id WHERE (Cities.name = 'St. Petersburg') or (Users.city_id IS NULL)
    Andrey lives in St. Petersburg
    Functions and group by:
    SQL: SELECT Cities.name, COUNT(Users.id) FROM Cities INNER JOIN Users ON Cities.id = Users.city_id GROUP BY Cities.name
    1 user(s) live(s) in St. Petersburg
    2 user(s) live(s) in Munich
    SQL: DROP TABLE Users
    SQL: DROP TABLE Cities

DAO sample

import org.jetbrains.exposed.sql.*
import org.jetbrains.exposed.sql.transactions.transaction
import org.jetbrains.exposed.sql.SchemaUtils.create
import org.jetbrains.exposed.dao.*

object Users : IntIdTable() {
    val name = varchar("name", 50).index()
    val city = reference("city", Cities)
    val age = integer("age")
}

object Cities: IntIdTable() {
    val name = varchar("name", 50)
}

class User(id: EntityID<Int>) : IntEntity(id) {
    companion object : IntEntityClass<User>(Users)

    var name by Users.name
    var city by City referencedOn Users.city
    var age by Users.age
}

class City(id: EntityID<Int>) : IntEntity(id) {
    companion object : IntEntityClass<City>(Cities)

    var name by Cities.name
    val users by User referrersOn Users.city
}

fun main(args: Array<String>) {
    Database.connect("jdbc:h2:mem:test", driver = "org.h2.Driver")

    transaction {
        logger.addLogger(StdOutSqlLogger)

        create (Cities, Users)

        val stPete = City.new {
            name = "St. Petersburg"
        }

        val munich = City.new {
            name = "Munich"
        }

        User.new {
            name = "a"
            city = stPete
            age = 5
        }

        User.new {
            name = "b"
            city = stPete
            age = 27
        }

        User.new {
            name = "c"
            city = munich
            age = 42
        }

        println("Cities: ${City.all().joinToString {it.name}}")
        println("Users in ${stPete.name}: ${stPete.users.joinToString {it.name}}")
        println("Adults: ${User.find { Users.age greaterEq 18 }.joinToString {it.name}}")
    }
}

Outputs:

    SQL: CREATE TABLE IF NOT EXISTS Cities (id INT AUTO_INCREMENT NOT NULL, name VARCHAR(50) NOT NULL, CONSTRAINT pk_Cities PRIMARY KEY (id))
    SQL: CREATE TABLE IF NOT EXISTS Users (id INT AUTO_INCREMENT NOT NULL, name VARCHAR(50) NOT NULL, city INT NOT NULL, age INT NOT NULL, CONSTRAINT pk_Users PRIMARY KEY (id))
    SQL: CREATE INDEX Users_name ON Users (name)
    SQL: ALTER TABLE Users ADD FOREIGN KEY (city) REFERENCES Cities(id)
    SQL: INSERT INTO Cities (name) VALUES ('St. Petersburg'),('Munich')
    SQL: SELECT Cities.id, Cities.name FROM Cities
    Cities: St. Petersburg, Munich
    SQL: INSERT INTO Users (name, city, age) VALUES ('a', 1, 5),('b', 1, 27),('c', 2, 42)
    SQL: SELECT Users.id, Users.name, Users.city, Users.age FROM Users WHERE Users.city = 1
    Users in St. Petersburg: a, b
    SQL: SELECT Users.id, Users.name, Users.city, Users.age FROM Users WHERE Users.age >= 18
    Adults: b, c

More examples and documentation on the wiki.

Exposed open issues Ask a question     (View All Issues)
  • about 3 years How to connect mysql with url
  • about 3 years Read-only columns support
  • about 3 years Field Comment, table comment set by mapping support feature request
  • about 3 years Add MS SQL Server Dialect
  • about 3 years DAO is not DRY
  • about 3 years Is it possible create an entity class from a table with a composite primary key?
  • over 3 years Add Documentation
  • over 3 years Support natively data classes + repository based DAO
  • almost 5 years Syntax seems degraded since the fork
Exposed open pull requests (View All Pulls)
  • Move to Gradle, fix naming, publish to my maven repo
  • Add PostgreSQL dialect (base functional)
  • Allowed user to set default isolation level
  • Oracle dialect
  • inList Op should accept iterable and not just list.
  • Add timezone to DateTime column type
  • Added a UUID Helper class and example
  • fix naming convention issues
  • add transaction without db method
  • #268 Add support for check constraints.
  • Add custom name for constraints
Exposed questions on Stackoverflow (View All Questions)
  • Reset Views Exposed Filter with Input Required
  • Enable resolutions not exposed by display programmatically on NVIDIA GPUs
  • How to put exposed filter in a separate block in a view in drupal 7
  • Angular 2 - how to inject dependencies to custom class which is not a component and isn't exposed as service
  • C#: Return managed enums exposed from a c++ library and make them available to other referenced projects
  • Are the methods of my MATLAB object exposed from the compiled .NET component with MATLAB Compiler NET?
  • How to delete Serializable entity exposed with Spring data rest and spring data mongo
  • Drupal 7 Views Exposed Filters
  • Drupal 7, Search_API_Views exposed date filter
  • query android app for exposed intents
  • properties exposed according to authorization level in breeze controller
  • Can NServiceBus's use of NHibernate be exposed in logging with Log4Net?
  • Is the Content-Type charset not exposed from HttpResponseMessage?
  • How to reference C# dll located in different folder to a C# winforms exe in different folder which uses Interface exposed by that dll
  • Provide documentation for API methods exposed through Google Cloud Endpoints
  • Hard lines/boxes exposed behind extreme box-shadow effect?
  • SAML 2.0 protocol exposed as Web Service
  • Should Domain Entities be exposed as Interfaces or as Plain Objects?
  • GAE - why Post request has parameters exposed in URL?
  • Node module property how to exposed and update
  • What kind of data exposed from linkedin API
  • Flowgear Google App Engine Database Connection via internate exposed
  • Why are html ids exposed as global variables in browser
  • How to create Better Exposed Filters for my non Drupal website
  • Why doesn't my pod respond to requests on the exposed port?
  • Is there a compiler bug exposed by my implementation of an is_complete type trait?
  • Best Practice to Avoid website's credential information to be exposed
  • Postfix header being exposed
  • Requirements com.adobe.granite.xss not found on bundle start, but exposed
  • Do Node.js-hosted files have their code exposed?
Exposed list of languages used
Other projects in Kotlin