{"id":27066943,"url":"https://github.com/mfarsikov/kotlite","last_synced_at":"2025-04-05T19:29:24.634Z","repository":{"id":57721435,"uuid":"322536930","full_name":"mfarsikov/kotlite","owner":"mfarsikov","description":"SQL generator and result set mapper for Sqlite and Kotlin","archived":false,"fork":false,"pushed_at":"2022-10-02T21:18:22.000Z","size":341,"stargazers_count":7,"open_issues_count":1,"forks_count":1,"subscribers_count":2,"default_branch":"master","last_synced_at":"2023-09-20T09:28:04.495Z","etag":null,"topics":["entities","kapt","kotlin","orm","sql","sql-generator","sqlite","sqlite-jdbc","sqlite-orm","sqlite3"],"latest_commit_sha":null,"homepage":"","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/mfarsikov.png","metadata":{"files":{"readme":"readme.md","changelog":null,"contributing":null,"funding":null,"license":"LICENSE","code_of_conduct":null,"threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":null,"support":null}},"created_at":"2020-12-18T08:37:44.000Z","updated_at":"2023-02-11T01:39:04.000Z","dependencies_parsed_at":"2023-01-19T02:30:36.376Z","dependency_job_id":null,"html_url":"https://github.com/mfarsikov/kotlite","commit_stats":null,"previous_names":[],"tags_count":7,"template":null,"template_full_name":null,"repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/mfarsikov%2Fkotlite","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/mfarsikov%2Fkotlite/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/mfarsikov%2Fkotlite/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/mfarsikov%2Fkotlite/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/mfarsikov","download_url":"https://codeload.github.com/mfarsikov/kotlite/tar.gz/refs/heads/master","host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":247390408,"owners_count":20931414,"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":["entities","kapt","kotlin","orm","sql","sql-generator","sqlite","sqlite-jdbc","sqlite-orm","sqlite3"],"created_at":"2025-04-05T19:29:24.068Z","updated_at":"2025-04-05T19:29:24.620Z","avatar_url":"https://github.com/mfarsikov.png","language":"Kotlin","funding_links":[],"categories":[],"sub_categories":[],"readme":"![Maven](https://img.shields.io/maven-central/v/com.github.mfarsikov/kotlite-kapt?style=flat-square\u0026color=blue)\n![Github](https://img.shields.io/github/workflow/status/mfarsikov/kotlite/master/master?label=tests)\n\u003cimg src=\"misc/kotlin-logo.svg\" alt=\"drawing\" width=\"20\"/\u003e\n\n# Kotlite\n\nNot an ORM.\n\nGenerates inspectable SQL queries before compile time rather than in runtime.\n\n`Kotlite = ORM - bullshit`\n\n## Quick start\n\n#### Gradle\n\n```kotlin\nplugins {\n    id(\"com.google.devtools.ksp\") version \"1.7.20-1.0.6\"\n    kotlin(\"plugin.serialization\") // for serializing collections as JSON\n}\n\nrepositories {\n    mavenCentral()\n    jcenter() // Despite jcenter announced service decommission, Kotlite depends on KotlinBard which is not moved yet\n}\n\ndependencies {\n  implementation(\"com.github.mfarsikov:kotlite-core:0.9.0\") // library containing annotations and classes used in compile time\n\n  ksp(\"com.github.mfarsikov:kotlite-ksp:0.9.0\") // Kotlin symbol processor, generates repositories code before compilation\n}\n\nksp {\n  arguments {\n    arg(\"kotlite.db.qualifiedName\", \"my.pack.DB\") // default database class name\n    arg(\"kotlite.spring\", \"false\") // marks database class as Spring's component\n  }\n}\n```\n\n#### Create entities and declare repositories\n\n```kotlin\nimport kotlite.annotations.Id\nimport kotlite.annotations.SqliteRepository\nimport kotlite.aux.Repository\n\ndata class Person(\n  @Id\n  val id: UUID,\n  val name: String,\n  val birthDate: LocalDate,\n)\n\n@SqliteRepository\ninterface PersonRepository : Repository\u003cPerson\u003e {\n    fun save(person: Person)\n    fun findBy(birthDate: LocalDate): List\u003cPerson\u003e\n}\n\n```\n\n#### Generate the code\n\n`./gradlew kspKotlin` generates in the folder `build/generated/ksp/main` two classes:\n`PersonRepositoryImpl` and `DB`\n\u003cdetails\u003e\n\u003csummary\u003eGenerated code\u003c/summary\u003e\n\n```kotlin\n\n@Generated\ninternal class PersonRepositoryImpl(\n  private val connection: Connection\n) : PersonRepository {\n  \n  public override fun findBy(birthDate: LocalDate): List\u003cPerson\u003e {\n    val query = \"\"\"\n        |SELECT \"birth_date\", \"id\", \"name\"\n        |FROM \"person\"\n        |WHERE \"birth_date\" = ?\n        \"\"\".trimMargin()\n    return connection.prepareStatement(query).use {\n      it.setObject(1, birthDate)\n      it.executeQuery().use {\n        val acc = mutableListOf\u003cPerson\u003e()\n        while (it.next()) {\n          acc +=\n             Person(\n              birthDate = it.getObject(\"birth_date\", java.time.LocalDate::class.java),\n              id = it.getObject(\"id\", UUID::class.java),\n              name = it.getString(\"name\"),\n            )\n        }\n        acc\n      }\n    }\n  }\n\n  public override fun save(person: Person): Unit {\n    val query = \"\"\"\n        |INSERT INTO \"person\"\n        |(\"birth_date\", \"id\", \"name\")\n        |VALUES (?, ?, ?)\n        |ON CONFLICT (id) DO \n        |UPDATE SET \"birth_date\" = EXCLUDED.\"birth_date\", \"id\" = EXCLUDED.\"id\", \"name\" = EXCLUDED.\"name\"\n        |\"\"\".trimMargin()\n    return connection.prepareStatement(query).use {\n      it.setObject(1, person.birthDate)\n      it.setObject(2, person.id)\n      it.setString(3, person.name)\n      it.executeUpdate()\n    }\n  }\n}\n```\n\n\u003c/details\u003e\n\n#### Usage\n\n```kotlin\nval db = DB(dataSource) // create DB access object\n\ndb.transaction {\n  // inside the transaction all repositories are accessible through 'this'\n  personRepository.save(\n    Person(\n      id = UUID.random(),\n      name = \"John Doe\",\n      birthDate = LocalDate.now(),\n    )\n  )\n}\n\nval bornToday = db.transaction(readOnly = true) {\n    personRepository.findBy(birthDate = LocalDate.now())\n}\n\n```\n\n## Synopsis\n\n* Maps Kotlin classes to Sqlite tables\n* Generates SpringData-like repositories with\n    * predefined query methods(`saveAll`, `deleteAll`, `findAll`)\n    * custom query methods (like `findByLastName`)\n    * methods using native SQL (`@Query(\"select ...\")`)\n    * query methods returning projections, scalar types and their lists\n* Code and queries are generated during build process, before compilation\n* Generated code is properly formatted and human-friendly\n* Explicit transaction management (DSL instead of annotations driven)\n* Sqlite specific\n* Uses native SQL and JDBC\n* Uses immutable Kotlin data classes as 'entities'\n* Maps nested object's properties into a single table (like JPA `@Embeddable`)\n* Serializes Kotlin collections as JSONB type in sqlite\n* Generates schema validations\n\nUnlike popular ORM:\n\n* No reflection and runtime magic\n* No lazy loading\n* No automatic joins, and sub selects (no \"N+1\" problem)\n* No query languages other than SQL\n* No vendor agnostic\n* No implicit type conversions\n* No queries triggered by entity's getters\n* No \"managed\" state\n* No caches\n* No \"object relational impedance mismatch\"\n* No inheritance resolve strategies\n* No transaction managers\n\n## Rationale\n\nThe intention was to make database interactions (queries and transactions) explicit.\nGenerate boiler plate code (like trivial queries, and result mappings).\nGive ability to write complex queries, and map their results automatically.\nUse full power of Sqlite.\n\nAvoid accidental complexity\n\n## Documentation\n\nhttps://mfarsikov.github.io/kotlite/\n\n## Example\n\nSee `example` project\n\n`./gradlew sqlite-example:kspKotlin` generates database classes in `example/build/generated/ksp/main`\n\n`./gradlew sqlite-example:test` runs real queries against Sqlite DB\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fmfarsikov%2Fkotlite","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fmfarsikov%2Fkotlite","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fmfarsikov%2Fkotlite/lists"}