{"id":13427838,"url":"https://github.com/JetBrains/Exposed","last_synced_at":"2025-03-16T00:32:38.044Z","repository":{"id":37431351,"uuid":"11765017","full_name":"JetBrains/Exposed","owner":"JetBrains","description":"Kotlin SQL Framework","archived":false,"fork":false,"pushed_at":"2025-03-07T15:47:07.000Z","size":32137,"stargazers_count":8589,"open_issues_count":174,"forks_count":707,"subscribers_count":129,"default_branch":"main","last_synced_at":"2025-03-11T03:19:38.579Z","etag":null,"topics":["dao","kotlin","orm","sql"],"latest_commit_sha":null,"homepage":"http://jetbrains.github.io/Exposed/","language":"Kotlin","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":"apache-2.0","status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/JetBrains.png","metadata":{"files":{"readme":"README.md","changelog":"CHANGELOG.md","contributing":"docs/contributing.html","funding":null,"license":"LICENSE.txt","code_of_conduct":null,"threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":null,"support":null,"governance":null,"roadmap":null,"authors":null,"dei":null,"publiccode":null,"codemeta":null}},"created_at":"2013-07-30T12:55:27.000Z","updated_at":"2025-03-10T14:30:43.000Z","dependencies_parsed_at":"2024-01-29T13:04:57.167Z","dependency_job_id":"8b156799-2327-47f1-b0c5-277ab6bcdb79","html_url":"https://github.com/JetBrains/Exposed","commit_stats":{"total_commits":2594,"total_committers":214,"mean_commits":"12.121495327102803","dds":0.5454895913646878,"last_synced_commit":"d3c60f28674c4b96c1aa1e64531fca4f055a23ca"},"previous_names":[],"tags_count":112,"template":false,"template_full_name":null,"repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/JetBrains%2FExposed","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/JetBrains%2FExposed/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/JetBrains%2FExposed/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/JetBrains%2FExposed/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/JetBrains","download_url":"https://codeload.github.com/JetBrains/Exposed/tar.gz/refs/heads/main","host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":243809865,"owners_count":20351403,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2022-07-04T15:15:14.044Z","host_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub","repositories_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories","repository_names_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repository_names","owners_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners"}},"keywords":["dao","kotlin","orm","sql"],"created_at":"2024-07-31T01:00:41.102Z","updated_at":"2025-03-16T00:32:38.008Z","avatar_url":"https://github.com/JetBrains.png","language":"Kotlin","readme":"\u003cdiv align=\"center\"\u003e\n\n  \u003cpicture\u003e\n    \u003csource media=\"(prefers-color-scheme: dark)\" srcset=\"./docs/logo-dark.png\" width=\"315\"\u003e\n    \u003cimg alt=\"Exposed logo\" src=\"./docs/logo-light.png\" width=\"315\"\u003e\n  \u003c/picture\u003e\n\n\u003c/div\u003e\n\u003cbr\u003e\u003cbr\u003e\n\n\u003cdiv align=\"center\"\u003e\n\n[![JetBrains team project](https://jb.gg/badges/team.svg)](https://confluence.jetbrains.com/display/ALL/JetBrains+on+GitHub)\n[![Slack Channel](https://img.shields.io/badge/chat-exposed-yellow.svg?logo=slack)](https://kotlinlang.slack.com/messages/exposed/)\n[![TC Build status](https://exposed.teamcity.com/app/rest/builds/buildType:id:Exposed_Build/statusIcon.svg)](https://exposed.teamcity.com/viewType.html?buildTypeId=Exposed_Build\u0026guest=1)\n[![Maven Central](https://maven-badges.herokuapp.com/maven-central/org.jetbrains.exposed/exposed-core/badge.svg)](https://maven-badges.herokuapp.com/maven-central/org.jetbrains.exposed/exposed-core)\n[![GitHub License](https://img.shields.io/badge/license-Apache%20License%202.0-blue.svg?style=flat)](https://www.apache.org/licenses/LICENSE-2.0)\n\n\u003c/div\u003e\n\n## Welcome to **Exposed**, an ORM framework for [Kotlin](https://github.com/JetBrains/kotlin).\n\nExposed is a lightweight SQL library on top of a JDBC driver for the Kotlin language.\nExposed has two flavors of database access: typesafe SQL wrapping DSL and lightweight Data Access Objects (DAO).\n\nWith Exposed, you have two options for database access: wrapping DSL and a lightweight DAO. Our official mascot is the cuttlefish, which is well-known for its outstanding mimicry ability that enables it to blend seamlessly into any environment.\nSimilar to our mascot, Exposed can be used to mimic a variety of database engines, which helps you to build applications without dependencies on any specific database engine and to switch between them with very little or no changes.\n\n## Supported Databases\n\n- H2 (versions 2.x; 1.x version is deprecated and will be removed in future releases)\n- [![MariaDB](https://img.shields.io/badge/MariaDB-003545?style=for-the-badge\u0026logo=mariadb\u0026logoColor=white)](https://github.com/mariadb-corporation/mariadb-connector-j)\n- [![MySQL](https://img.shields.io/badge/mysql-4479A1.svg?style=for-the-badge\u0026logo=mysql\u0026logoColor=white)](https://github.com/mysql/mysql-connector-j)\n- [![Oracle](https://img.shields.io/badge/Oracle-F80000?style=for-the-badge\u0026logo=oracle\u0026logoColor=white)](https://www.oracle.com/ca-en/database/technologies/appdev/jdbc-downloads.html)\n- [![Postgres](https://img.shields.io/badge/postgres-%23316192.svg?style=for-the-badge\u0026logo=postgresql\u0026logoColor=white)](https://jdbc.postgresql.org/)\n  (Also, PostgreSQL using the [pgjdbc-ng](https://impossibl.github.io/pgjdbc-ng/) JDBC driver)\n- [![MicrosoftSQLServer](https://img.shields.io/badge/Microsoft%20SQL%20Server-CC2927?style=for-the-badge\u0026logo=microsoft%20sql%20server\u0026logoColor=white)](https://github.com/microsoft/mssql-jdbc)\n- [![SQLite](https://img.shields.io/badge/sqlite-%2307405e.svg?style=for-the-badge\u0026logo=sqlite\u0026logoColor=white)](https://github.com/xerial/sqlite-jdbc)\n\n## Dependencies\n\n### Maven Central configuration\n\nReleases of Exposed are available in the Maven Central repository. You can declare this repository in your build script as follows:\n\n#### Gradle Groovy and Kotlin DSL\n\n**Warning:** You might need to set your Kotlin JVM target to 8, and when using Spring to 17, in order for this to work properly:\n\n```kotlin\nrepositories {\n    // Versions after 0.30.1\n    // Versions before 0.30.1 is unavailable for now\n    mavenCentral()\n}\n```\n\n#### Maven\n\nThe Maven Central repository is enabled by default for Maven users.\n\n### Exposed modules\n\n`Exposed` consists of the following modules:\n\n* exposed-core - base module, which contains both DSL api along with mapping\n* exposed-crypt - provides additional column types to store encrypted data in DB and encode/decode it on client-side\n* exposed-dao - DAO api\n* exposed-java-time - date-time extensions based on Java8 Time API\n* exposed-jdbc - transport level implementation based on Java JDBC API\n* exposed-jodatime - date-time extensions based on JodaTime library\n* exposed-json - JSON and JSONB data type extensions\n* exposed-kotlin-datetime - date-time extensions based on kotlinx-datetime\n* exposed-money - extensions to support MonetaryAmount from \"javax.money:money-api\"\n* exposed-spring-boot-starter - a starter for [Spring Boot](https://spring.io/projects/spring-boot) to utilize Exposed as the ORM instead\n  of [Hibernate](https://hibernate.org/)\n\n```xml\n\n\u003cdependencies\u003e\n    \u003cdependency\u003e\n        \u003cgroupId\u003eorg.jetbrains.exposed\u003c/groupId\u003e\n        \u003cartifactId\u003eexposed-core\u003c/artifactId\u003e\n        \u003cversion\u003e0.60.0\u003c/version\u003e\n    \u003c/dependency\u003e\n    \u003cdependency\u003e\n        \u003cgroupId\u003eorg.jetbrains.exposed\u003c/groupId\u003e\n        \u003cartifactId\u003eexposed-crypt\u003c/artifactId\u003e\n        \u003cversion\u003e0.60.0\u003c/version\u003e\n    \u003c/dependency\u003e\n    \u003cdependency\u003e\n        \u003cgroupId\u003eorg.jetbrains.exposed\u003c/groupId\u003e\n        \u003cartifactId\u003eexposed-dao\u003c/artifactId\u003e\n        \u003cversion\u003e0.60.0\u003c/version\u003e\n    \u003c/dependency\u003e\n    \u003cdependency\u003e\n        \u003cgroupId\u003eorg.jetbrains.exposed\u003c/groupId\u003e\n        \u003cartifactId\u003eexposed-java-time\u003c/artifactId\u003e\n        \u003cversion\u003e0.60.0\u003c/version\u003e\n    \u003c/dependency\u003e\n    \u003cdependency\u003e\n        \u003cgroupId\u003eorg.jetbrains.exposed\u003c/groupId\u003e\n        \u003cartifactId\u003eexposed-jdbc\u003c/artifactId\u003e\n        \u003cversion\u003e0.60.0\u003c/version\u003e\n    \u003c/dependency\u003e\n    \u003cdependency\u003e\n        \u003cgroupId\u003eorg.jetbrains.exposed\u003c/groupId\u003e\n        \u003cartifactId\u003eexposed-jodatime\u003c/artifactId\u003e\n        \u003cversion\u003e0.60.0\u003c/version\u003e\n    \u003c/dependency\u003e\n    \u003cdependency\u003e\n        \u003cgroupId\u003eorg.jetbrains.exposed\u003c/groupId\u003e\n        \u003cartifactId\u003eexposed-json\u003c/artifactId\u003e\n        \u003cversion\u003e0.60.0\u003c/version\u003e\n    \u003c/dependency\u003e\n    \u003cdependency\u003e\n        \u003cgroupId\u003eorg.jetbrains.exposed\u003c/groupId\u003e\n        \u003cartifactId\u003eexposed-kotlin-datetime\u003c/artifactId\u003e\n        \u003cversion\u003e0.60.0\u003c/version\u003e\n    \u003c/dependency\u003e\n    \u003cdependency\u003e\n        \u003cgroupId\u003eorg.jetbrains.exposed\u003c/groupId\u003e\n        \u003cartifactId\u003eexposed-money\u003c/artifactId\u003e\n        \u003cversion\u003e0.60.0\u003c/version\u003e\n    \u003c/dependency\u003e\n    \u003cdependency\u003e\n        \u003cgroupId\u003eorg.jetbrains.exposed\u003c/groupId\u003e\n        \u003cartifactId\u003eexposed-spring-boot-starter\u003c/artifactId\u003e\n        \u003cversion\u003e0.60.0\u003c/version\u003e\n    \u003c/dependency\u003e\n\u003c/dependencies\u003e\n\n```\n\n#### Gradle Groovy\n\n```groovy\ndependencies {\n    implementation 'org.jetbrains.exposed:exposed-core:0.60.0'\n    implementation 'org.jetbrains.exposed:exposed-crypt:0.60.0'\n    implementation 'org.jetbrains.exposed:exposed-dao:0.60.0'\n    implementation 'org.jetbrains.exposed:exposed-jdbc:0.60.0'\n    \n    implementation 'org.jetbrains.exposed:exposed-jodatime:0.60.0'\n    // or\n    implementation 'org.jetbrains.exposed:exposed-java-time:0.60.0'\n    // or\n    implementation 'org.jetbrains.exposed:exposed-kotlin-datetime:0.60.0'\n    \n    implementation 'org.jetbrains.exposed:exposed-json:0.60.0'\n    implementation 'org.jetbrains.exposed:exposed-money:0.60.0'\n    implementation 'org.jetbrains.exposed:exposed-spring-boot-starter:0.60.0'\n}\n```\n\n#### Gradle Kotlin DSL\n\nIn `build.gradle.kts`:\n\n```kotlin\nval exposedVersion: String by project\ndependencies {\n    implementation(\"org.jetbrains.exposed:exposed-core:$exposedVersion\")\n    implementation(\"org.jetbrains.exposed:exposed-crypt:$exposedVersion\")\n    implementation(\"org.jetbrains.exposed:exposed-dao:$exposedVersion\")\n    implementation(\"org.jetbrains.exposed:exposed-jdbc:$exposedVersion\")\n    \n    implementation(\"org.jetbrains.exposed:exposed-jodatime:$exposedVersion\")\n    // or\n    implementation(\"org.jetbrains.exposed:exposed-java-time:$exposedVersion\")\n    // or\n    implementation(\"org.jetbrains.exposed:exposed-kotlin-datetime:$exposedVersion\")\n    \n    implementation(\"org.jetbrains.exposed:exposed-json:$exposedVersion\")\n    implementation(\"org.jetbrains.exposed:exposed-money:$exposedVersion\")\n    implementation(\"org.jetbrains.exposed:exposed-spring-boot-starter:$exposedVersion\")\n}\n```\n\nand in `gradle.properties`\n\n```\nexposedVersion=0.60.0\n```\n\n## Samples\n\nCheck out the [samples](samples/README.md) for a quick start.\n\n## Links\n\nCurrently, Exposed is available for **maven/gradle builds**. Check the [Maven Central](https://search.maven.org/search?q=g:org.jetbrains.exposed) and read [Getting Started](https://www.jetbrains.com/help/exposed/getting-started-with-exposed.html) to get an insight on setting up Exposed.\n\u003cbr\u003e\u003cbr\u003e\nFor more information visit the links below:\n\n-   [Documentation](https://www.jetbrains.com/help/exposed/home.html) with examples and docs\n-   [Contributing to Exposed](#contributing)\n-   [Migration Guide](https://www.jetbrains.com/help/exposed/migration-guide.html)\n-   [Breaking changes](https://www.jetbrains.com/help/exposed/breaking-changes.html) and any migration details\n-   [Slack Channel](https://kotlinlang.slack.com/messages/exposed/)\n-   [Filing Issues](#contributing)\n-   [Issue Tracker](https://youtrack.jetbrains.com/issues/EXPOSED)\n\u003cbr\u003e\u003cbr\u003e\n\n## Community\n\nDo you have questions? Feel free to [request an invitation](https://surveys.jetbrains.com/s3/kotlin-slack-sign-up) for the [kotlinlang slack](https://kotlinlang.slack.com/) and join the project conversation at our [#exposed](https://kotlinlang.slack.com/messages/exposed/) channel.\n\n## Contributing\n\nWe encourage your feedback in any form, such as feature requests, bug reports, documentation updates, and questions.\nNote that we are moving away from GitHub Issues for this reporting. Log any new requests on [YouTrack](https://youtrack.jetbrains.com/issues/EXPOSED).\nWhile issues are visible publicly, either creating a new issue or commenting on an existing one does require logging in to YouTrack.\n\nWe also actively welcome your pull requests. However, linking your work to an [existing issue](https://youtrack.jetbrains.com/issues/EXPOSED) is preferred.\n\n\nSee the full [contribution guide](https://www.jetbrains.com/help/exposed/contributing.html) for more details.\n\nBy contributing to the Exposed project, you agree that your contributions will be licensed under [Apache License, Version 2.0](https://www.apache.org/licenses/LICENSE-2.0).\n\u003cbr\u003e\u003cbr\u003e\n\n## Examples\n\n### SQL DSL\n\n```kotlin\nimport org.jetbrains.exposed.sql.*\nimport org.jetbrains.exposed.sql.SqlExpressionBuilder.like\nimport org.jetbrains.exposed.sql.transactions.transaction\n\nobject Users : Table() {\n    val id: Column\u003cString\u003e = varchar(\"id\", 10)\n    val name: Column\u003cString\u003e = varchar(\"name\", length = 50)\n    val cityId: Column\u003cInt?\u003e = (integer(\"city_id\") references Cities.id).nullable()\n\n    override val primaryKey = PrimaryKey(id, name = \"PK_User_ID\") // name is optional here\n}\n\nobject Cities : Table() {\n    val id: Column\u003cInt\u003e = integer(\"id\").autoIncrement()\n    val name: Column\u003cString\u003e = varchar(\"name\", 50)\n\n    override val primaryKey = PrimaryKey(id, name = \"PK_Cities_ID\")\n}\n\nfun main() {\n    Database.connect(\"jdbc:h2:mem:test\", driver = \"org.h2.Driver\", user = \"root\", password = \"\")\n\n    transaction {\n        addLogger(StdOutSqlLogger)\n\n        SchemaUtils.create(Cities, Users)\n\n        val saintPetersburgId = Cities.insert {\n            it[name] = \"St. Petersburg\"\n        } get Cities.id\n\n        val munichId = Cities.insert {\n            it[name] = \"Munich\"\n        } get Cities.id\n\n        val pragueId = Cities.insert {\n            it.update(name, stringLiteral(\"   Prague   \").trim().substring(1, 2))\n        }[Cities.id]\n\n        val pragueName = Cities.selectAll().where { Cities.id eq pragueId }.single()[Cities.name]\n        println(\"pragueName = $pragueName\")\n\n        Users.insert {\n            it[id] = \"andrey\"\n            it[name] = \"Andrey\"\n            it[Users.cityId] = saintPetersburgId\n        }\n\n        Users.insert {\n            it[id] = \"sergey\"\n            it[name] = \"Sergey\"\n            it[Users.cityId] = munichId\n        }\n\n        Users.insert {\n            it[id] = \"eugene\"\n            it[name] = \"Eugene\"\n            it[Users.cityId] = munichId\n        }\n\n        Users.insert {\n            it[id] = \"alex\"\n            it[name] = \"Alex\"\n            it[Users.cityId] = null\n        }\n\n        Users.insert {\n            it[id] = \"smth\"\n            it[name] = \"Something\"\n            it[Users.cityId] = null\n        }\n\n        Users.update({ Users.id eq \"alex\" }) {\n            it[name] = \"Alexey\"\n        }\n\n        Users.deleteWhere{ Users.name like \"%thing\" }\n\n        println(\"All cities:\")\n\n        for (city in Cities.selectAll()) {\n            println(\"${city[Cities.id]}: ${city[Cities.name]}\")\n        }\n\n        println(\"Manual join:\")\n        \n        (Users innerJoin Cities)\n            .select(Users.name, Cities.name)\n            .where {\n                (Users.id.eq(\"andrey\") or Users.name.eq(\"Sergey\")) and\n                    Users.id.eq(\"sergey\") and Users.cityId.eq(Cities.id)\n            }.forEach { \n                println(\"${it[Users.name]} lives in ${it[Cities.name]}\") \n            }\n\n        println(\"Join with foreign key:\")\n\n        (Users innerJoin Cities)\n            .select(Users.name, Users.cityId, Cities.name)\n            .where { Cities.name.eq(\"St. Petersburg\") or Users.cityId.isNull() }\n            .forEach { \n                if (it[Users.cityId] != null) { \n                    println(\"${it[Users.name]} lives in ${it[Cities.name]}\") \n                } \n                else { \n                    println(\"${it[Users.name]} lives nowhere\") \n                } \n            }\n\n        println(\"Functions and group by:\")\n\n        ((Cities innerJoin Users)\n            .select(Cities.name, Users.id.count())\n            .groupBy(Cities.name)\n            ).forEach {\n                val cityName = it[Cities.name]\n                val userCount = it[Users.id.count()]\n\n                if (userCount \u003e 0) {\n                    println(\"$userCount user(s) live(s) in $cityName\")\n                } else {\n                    println(\"Nobody lives in $cityName\")\n                }\n            }\n\n        SchemaUtils.drop(Users, Cities)\n    }\n}\n\n```\n\nGenerated SQL:\n\n```sql\n    SQL: CREATE TABLE IF NOT EXISTS Cities (id INT AUTO_INCREMENT, name VARCHAR(50) NOT NULL, CONSTRAINT PK_Cities_ID PRIMARY KEY (id))\n    SQL: CREATE TABLE IF NOT EXISTS Users (id VARCHAR(10), name VARCHAR(50) NOT NULL, city_id INT NULL, CONSTRAINT PK_User_ID PRIMARY KEY (id), CONSTRAINT FK_Users_city_id__ID FOREIGN KEY (city_id) REFERENCES Cities(id) ON DELETE RESTRICT ON UPDATE RESTRICT)\n    SQL: INSERT INTO Cities (name) VALUES ('St. Petersburg')\n    SQL: INSERT INTO Cities (name) VALUES ('Munich')\n    SQL: INSERT INTO Cities (name) VALUES (SUBSTRING(TRIM('   Prague   '), 1, 2))\n    SQL: SELECT Cities.id, Cities.name FROM Cities WHERE Cities.id = 3\n    pragueName = Pr\n    SQL: INSERT INTO Users (id, name, city_id) VALUES ('andrey', 'Andrey', 1)\n    SQL: INSERT INTO Users (id, name, city_id) VALUES ('sergey', 'Sergey', 2)\n    SQL: INSERT INTO Users (id, name, city_id) VALUES ('eugene', 'Eugene', 2)\n    SQL: INSERT INTO Users (id, name, city_id) VALUES ('alex', 'Alex', NULL)\n    SQL: INSERT INTO Users (id, name, city_id) VALUES ('smth', 'Something', NULL)\n    SQL: UPDATE Users SET name='Alexey' WHERE Users.id = 'alex'\n    SQL: DELETE FROM Users WHERE Users.name LIKE '%thing'\n    All cities:\n    SQL: SELECT Cities.id, Cities.name FROM Cities\n    1: St. Petersburg\n    2: Munich\n    3: Pr\n    Manual join:\n    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)\n    Sergey lives in Munich\n    Join with foreign key:\n    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)\n    Andrey lives in St. Petersburg\n    Functions and group by:\n    SQL: SELECT Cities.name, COUNT(Users.id) FROM Cities INNER JOIN Users ON Cities.id = Users.city_id GROUP BY Cities.name\n    1 user(s) live(s) in St. Petersburg\n    2 user(s) live(s) in Munich\n    SQL: DROP TABLE IF EXISTS Users\n    SQL: DROP TABLE IF EXISTS Cities\n```\n\n### DAO\n\n```kotlin\nimport org.jetbrains.exposed.dao.*\nimport org.jetbrains.exposed.dao.id.EntityID\nimport org.jetbrains.exposed.dao.id.IntIdTable\nimport org.jetbrains.exposed.sql.*\nimport org.jetbrains.exposed.sql.transactions.transaction\n\nobject Users : IntIdTable() {\n    val name = varchar(\"name\", 50).index()\n    val city = reference(\"city\", Cities)\n    val age = integer(\"age\")\n}\n\nobject Cities: IntIdTable() {\n    val name = varchar(\"name\", 50)\n}\n\nclass User(id: EntityID\u003cInt\u003e) : IntEntity(id) {\n    companion object : IntEntityClass\u003cUser\u003e(Users)\n\n    var name by Users.name\n    var city by City referencedOn Users.city\n    var age by Users.age\n}\n\nclass City(id: EntityID\u003cInt\u003e) : IntEntity(id) {\n    companion object : IntEntityClass\u003cCity\u003e(Cities)\n\n    var name by Cities.name\n    val users by User referrersOn Users.city\n}\n\nfun main() {\n    Database.connect(\"jdbc:h2:mem:test\", driver = \"org.h2.Driver\", user = \"root\", password = \"\")\n\n    transaction {\n        addLogger(StdOutSqlLogger)\n\n        SchemaUtils.create(Cities, Users)\n\n        val stPete = City.new {\n            name = \"St. Petersburg\"\n        }\n\n        val munich = City.new {\n            name = \"Munich\"\n        }\n\n        User.new {\n            name = \"a\"\n            city = stPete\n            age = 5\n        }\n\n        User.new {\n            name = \"b\"\n            city = stPete\n            age = 27\n        }\n\n        User.new {\n            name = \"c\"\n            city = munich\n            age = 42\n        }\n\n        println(\"Cities: ${City.all().joinToString { it.name }}\")\n        println(\"Users in ${stPete.name}: ${stPete.users.joinToString { it.name }}\")\n        println(\"Adults: ${User.find { Users.age greaterEq 18 }.joinToString { it.name }}\")\n    }\n}\n```\n\nGenerated SQL:\n\n```sql\n    SQL: CREATE TABLE IF NOT EXISTS Cities (id INT AUTO_INCREMENT PRIMARY KEY, name VARCHAR(50) NOT NULL)\n    SQL: CREATE TABLE IF NOT EXISTS Users (id INT AUTO_INCREMENT PRIMARY KEY, name VARCHAR(50) NOT NULL, city INT NOT NULL, age INT NOT NULL, CONSTRAINT FK_Users_city__ID FOREIGN KEY (city) REFERENCES Cities(id) ON DELETE RESTRICT ON UPDATE RESTRICT)\n    SQL: CREATE INDEX Users_name ON Users (name)\n    SQL: INSERT INTO Cities (name) VALUES ('St. Petersburg')\n    SQL: INSERT INTO Cities (name) VALUES ('Munich')\n    SQL: SELECT Cities.id, Cities.name FROM Cities\n    Cities: St. Petersburg, Munich\n    SQL: INSERT INTO Users (name, city, age) VALUES ('a', 1, 5)\n    SQL: INSERT INTO Users (name, city, age) VALUES ('b', 1, 27)\n    SQL: INSERT INTO Users (name, city, age) VALUES ('c', 2, 42)\n    SQL: SELECT Users.id, Users.name, Users.city, Users.age FROM Users WHERE Users.city = 1\n    Users in St. Petersburg: a, b\n    SQL: SELECT Users.id, Users.name, Users.city, Users.age FROM Users WHERE Users.age \u003e= 18\n    Adults: b, c\n```\n","funding_links":[],"categories":["Libraries","Kotlin","开源库和框架","\u003e 3k ★","Android 应用","数据库开发","必备开发库","Libraries and Frameworks"],"sub_categories":["数据库","Database","网络服务_其他","网络和数据"],"project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2FJetBrains%2FExposed","html_url":"https://awesome.ecosyste.ms/projects/github.com%2FJetBrains%2FExposed","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2FJetBrains%2FExposed/lists"}