Coder Social home page Coder Social logo

kotysa's Introduction

License: Unlicense Maven Central Kotlin

Kotysa

A light ORM that offers the idiomatic way to write Kotlin type-safe SQL for JVM and Android

  • Kotysa supports various drivers : JDBC, R2DBC, Vertx sqlclient
  • Kotysa supports various database engines : PostgreSQL, MySQL, Microsoft SQL Server, MariaDB, Oracle, H2
  • Kotysa supports SqLite on Android

See the project website for documentation and APIs.

Basic example

Kotysa is easy to use : 3 steps only

step 1 -> Create Kotlin entities

data classes are great for that !

data class Role(
        val label: String,
        val id: UUID = UUID.randomUUID()
)

data class User(
        val firstname: String,
        val roleId: UUID,
        val alias: String? = null,
        val id: Int? = null
)

step 2 -> Describe database model

Use our type-safe Tables DSL to map your entities with the database tables, this is the ORM (object-relational mapping) step

object Roles : H2Table<Role>("roles") {
    val id = uuid(Role::id)
        .primaryKey()
    val label = varchar(Role::label)
        .unique()
}

object Users : H2Table<User>("users") {
    val id = autoIncrementInteger(User::id)
        .primaryKey("PK_users")
    val firstname = varchar(User::firstname, "f_name")
    val roleId = uuid(User::roleId)
        .foreignKey(Roles.id, "FK_users_roles")
    val alias = varchar(User::alias)
}

// List all your mapped tables
private val tables = tables().h2(Roles, Users)

step 3 -> Write SQL queries

Use our type-safe SqlClient DSL, Kotysa executes SQL query for you !

val admins = (sqlClient selectFrom Users
        innerJoin Roles on Users.roleId eq Roles.id
        where Roles.label eq "admin"
        ).fetchAll() // returns all admin users

No annotations, no code generation, no proxy, no additional plugin, just regular Kotlin code ! No JPA, just pure SQL !

Contributors

Contributions are welcome.

  • Compile Kotysa with a JDK 17.
  • You need a local docker, like docker-ce : some tests use testcontainers to start real databases like PostgreSQL, MySQL...
  1. Clone this repo
git clone [email protected]:ufoss-org/kotysa.git
  1. Build project
./gradlew clean build

kotysa's People

Contributors

pull-vert avatar

Stargazers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

Watchers

 avatar  avatar  avatar  avatar  avatar

Forkers

lorefnon

kotysa's Issues

kotysa-coroutines-r2dbc example not working

I cloned this repository and run kotysa-coroutines-r2dbc module.
application throw exception like below.

Caused by: java.lang.NoClassDefFoundError: com/sample/USER (wrong name: com/sample/User)
	at java.base/java.lang.ClassLoader.defineClass1(Native Method) ~[na:na]
	at java.base/java.lang.ClassLoader.defineClass(ClassLoader.java:1012) ~[na:na]
	at java.base/java.security.SecureClassLoader.defineClass(SecureClassLoader.java:150) ~[na:na]
	at java.base/jdk.internal.loader.BuiltinClassLoader.defineClass(BuiltinClassLoader.java:862) ~[na:na]
	at java.base/jdk.internal.loader.BuiltinClassLoader.findClassOnClassPathOrNull(BuiltinClassLoader.java:760) ~[na:na]
	at java.base/jdk.internal.loader.BuiltinClassLoader.loadClassOrNull(BuiltinClassLoader.java:681) ~[na:na]
	at java.base/jdk.internal.loader.BuiltinClassLoader.loadClass(BuiltinClassLoader.java:639) ~[na:na]
	at java.base/jdk.internal.loader.ClassLoaders$AppClassLoader.loadClass(ClassLoaders.java:188) ~[na:na]
	at java.base/java.lang.ClassLoader.loadClass(ClassLoader.java:520) ~[na:na]
	at java.base/java.lang.Class.getDeclaredMethods0(Native Method) ~[na:na]
	at java.base/java.lang.Class.privateGetDeclaredMethods(Class.java:3402) ~[na:na]
	at java.base/java.lang.Class.getDeclaredMethods(Class.java:2504) ~[na:na]
	at org.springframework.util.ReflectionUtils.getDeclaredMethods(ReflectionUtils.java:463) ~[spring-core-5.3.14.jar:5.3.14]
	... 34 common frames omitted

thank you

coroutine transaction should expose CoroutineScope

public suspend fun <T : Any> execute(block: suspend CoroutineScope.(ReactorTransaction) -> T?): T?

Linked addition : add contract where it is usefull

contract {
    callsInPlace(block, InvocationKind.EXACTLY_ONCE)
}

add transaction support

Provide an API for functional transaction in kotysa-core.

For kotysa-spring-r2dbc transaction implementation will will be based on Spring TransactionalOperator

For kotysa-spring-jdbc transaction implementation will will be based on Spring TransactionTemplate

This features is in progress in Kotysa, waiting for next spring-fu release, that will support it ๐Ÿ‘

jdbc pseudo coroutines

Add a coroutines pseudo implementation to kotysa-jdbc.
This means that single actions will correctly be suspend functions, but a select returning several results would return a suspend List<T> instead of a Flow<T> in a full coroutines world.

Note : This module would use or be inspired by kotlin-coroutines-jdbc

Add multiplatform kotysa-sqlite with common and android

kotysa-core will become a kotlin multiplatform mobile (KMM) project (common for common API + SqLite, jvm for other DBs)

kotysa-sqlite (that depends on kotysa-core) will be a KMM project with

  • kotysa-sqlite-common : multiplatform common API for kotysa-sqlite
  • kotysa-sqlite-android (probably pretty much the same code as current kotysa-android) : provides a SqLite client using Android AOSP included, based on legacy SqLite Java client
  • kotysa-sqlite-ios not included in this issue (see #120) : ios SqLite client using SQLiter [1].
  • kotysa-sqlite-jvm not included in this issue (see #120)
  • kotysa-sqlite-js (maybe?) not included in this issue
  • kotysa-sqlite-native (maybe?) not included in this issue : could be other non ios native platforms SqLite client using SQLiter [1]

Guide : official KMM sample project and Multiplatform tutorial with Ktor and SqlDelight

[1] : SQLiter is a SQLite driver for Kotlin Multiplatform, currently supporting IOS and Windows, and may later target JVM/Android and all flavors of Native that support the sqlite3 c libraries.

Add insertAndReturn

Uses DB specific to return the inserted tuple :

  • RETURNING field1, field2... for MariaDB and PostgreSQL
  • SELECT field1, field2... for H2
  • OUTPUT field1, field2... for Microsoft SQL Server
  • Add an extra SELECT for MySQL, that uses LAST_INSERT_ID for auto-incremented PK
  • Add an extra SELECT for SqLite, that uses generated id returned by executeInsert

Add FROM in Kotysa query DSL

This will allow to do some requests that cannot be made with current implementation

SELECT role.name
FROM role
INNER JOIN user_role ON role.id = user_role.role_id
WHERE user_role.user_id = :userId

0.2.0 dependency updates

  • Kotlin 1.4.31
  • kotlinx-coroutines 1.4.2
  • kotlinx-datetime 0.1.1
  • spring-core 5.3.4 (included in Spring boot 2.4.x)
  • build with Gradle 6.8.3

Question: Can library this be used w/o spring dependencies?

We want to use it in Micronaut or Ktor... but in the docs it seems like it's only for Android and Spring... pulling in tons of extra dependencies for a db layer wouldn't be too nice, especially since in Micronaut, a big stress on AOP and not using runtime reflection is made, whereas in Spring AFAIK, not...

Add mandatory FROM syntax in Kotysa query DSL

This will allow to do some requests that cannot be made with current implementation

SELECT role.name
FROM role
INNER JOIN user_role ON role.id = user_role.role_id
WHERE user_role.user_id = :userId

Importing Kotysa via maven imposes tight coupling on Spring milestone/RC

Problem

In uploads to jcenter, kotysa-spring-data-r2dbc does not provide a natural maven pom, instead relying on a pom generated from gradle.

This pom declares Spring as a bom import, for example

      <dependency>
        <groupId>org.springframework</groupId>
        <artifactId>spring-framework-bom</artifactId>
        <version>5.3.0-RC1</version>
        <type>pom</type>
        <scope>import</scope>
      </dependency>

In my project, I am already importing the Spring bom at a higher priority, so it should override Kotysa's import. No problem there so far.

The problem however is in the milestone or RC imports. These are only present in Spring's Milestone repository. As the Kotysa spike branch in out project does not depend on this repository, it fails to find this version of Spring's bom (even though these versions would have been overridden anyway). As far as I can see so far, bom imports in a dependency cannot be excluded so I cannot prevent Kotysa from taking this action from my pom.

The error is simple enough and looks like Failed to read artifact descriptor for org.ufoss.kotysa:kotysa-spring-r2dbc:jar:0.1.7: Failure to find org.springframework:spring-framework-bom:pom:5.3.0-RC1

Possible Solutions

The local solution here is simple enough, to add that dependency on Spring Milestone to my pom. That's not always possible though in company projects.

I'm not sure if this is Kotysa's fault, or the gradle-to-maven conversion's fault, but unfortunately, this repo has the problem.

Unless Kotysa is depending on bleeding edge Spring features (which is possible, I haven't dug into the source yet), it might be best to use stable releases. Or change the build file in some way to encourage a conversion to a better pom.

jdbc module

Add a new kotysa-jdbc module without dependency, based only on Java JDBC. It provides a blocking implementation.

kotysa-r2dbc module

Add a new kotysa-r2dbc module with only r2dbc-spi dependency. It provides a coroutines implementation.

Kotlin object based API for Kotysa

I think it is time for a simpler syntax, a lot closer to real SQL.
Mapping classes will now be Kotlin objects (= singletons). They will be the entry point in queries.

This is a major change !

Support upsert functionality

At this moment I don't think it is possible to use upsert functionality using a DSL. It's quite useful as most of the popular SQL implementations somehow support this:

MySQL, MariaDB, H2 (with MySQL dialect): ON DUPLICATE KEY UPDATE ...
PostgreSQL, SQLite: ON CONFLICT [ON CONSTRAINT] ...

Fix Kotysa Transaction support

For kotysa-jdbc only : SqlClient must use the Connection from current Transaction (from ThreadLocal) if any, or start a new one.

Breaking change for this fix : sqlclient with kotysa-jdbc will now be an obtained from a javax.sql.DataSource

Optimize and simplify Unit tests

  1. See how to create Database just once, insert all entities, then execute all tests. At the end of all tests drop database (no need to delete entities before that).
    see junit-team/junit5#1555

  2. Make sure to have common test entities for types that are supported by every databases, there is way too much duplicated code in tests now !

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    ๐Ÿ–– Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. ๐Ÿ“Š๐Ÿ“ˆ๐ŸŽ‰

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google โค๏ธ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.