闲来无事,用 Kotlin 写了一个简单的 ORM

2021-08-23 17:18:44 +08:00
 actar

目前主要支持单表的 CRUD 和 DML 的 DSL 语法。

package io.github.zhaofanzhe.kom.example

import io.github.zhaofanzhe.kom.Database
import io.github.zhaofanzhe.kom.connection.ConnectionFactory
import io.github.zhaofanzhe.kom.entity.Entity
import io.github.zhaofanzhe.kom.express.Table
import io.github.zhaofanzhe.kom.toolkit.eq
import java.sql.Connection
import java.sql.DriverManager

fun main() {
    val database = getDatabase()

    // 创建表[目前不支持自动迁移]
    database.createTable(Users()).execute()
    database.createTable(Addresses()).execute()

    // 单表 CRUD
    // 目前插入数据,目前没有做主键的回填
    database.create(User(id = 1, username = "张三"))
    database.create(User(id = 2, username = "李四"))
    database.create(User(id = 3, username = "王五"))
    database.create(Address(address = "北京", userId = 1))
    database.create(Address(address = "上海", userId = 1))
    database.create(Address(address = "广州", userId = 2))
    database.create(Address(address = "深圳", userId = 3))

    val user = database.fetchOne(Users()) { it.username eq "王五" }

    // 根据主键更新
    user?.let {
        it.username = "王老五"
        database.save(it)
    }

    // 根据主键删除
    user?.let {
        database.delete(it)
    }

    // DSL 查询

    val users = Users()

    val addresses = Addresses()

    // 子查询
    val subQuery = database.selectFrom(users)
        .where(users.username eq "张三")
        .subQuery()

    // 左连接
    val express = database.select(users, addresses)
        .from(subQuery)
        .leftJoin(addresses).on(addresses.userId eq users.id)

    // 打印 SQL
    println(express)

    // 遍历获取数据
    express.fetchAll().forEach {
        println(it[users])
        println(it[addresses])
    }

    // 删除表
    database.dropTable(Users()).execute()
    database.dropTable(Addresses()).execute()

}

data class User(
    var id: Int = 0,
    var username: String = "",
) : Entity<Users>(Users::class) {
    constructor() : this(id = 0, username = "")
}

class Users : Table<User>(User::class) {
    val id = column(User::id).primaryKey().autoIncrement()
    val username = column(User::username).unique()
}

data class Address(
    var id: Int = 0,
    var address: String = "",
    var userId: Int = 0,
) : Entity<Addresses>(Addresses::class) {
    constructor() : this(id = 0, address = "", userId = 0)
}

class Addresses : Table<Address>(Address::class) {
    var id = column(Address::id).primaryKey().autoIncrement()
    var address = column(Address::address)
    var userId = column(Address::userId)
}

fun getDatabase(): Database {
    return Database(object : ConnectionFactory {
        override fun getConnection(): Connection {
            return DriverManager.getConnection("{url}", "{user}", "{password}")
        }
    })
}

Github 地址: Kom

另外,求个 star~

1978 次点击
所在节点    分享创造
7 条回复
xmt328
2021-08-24 11:52:31 +08:00
插眼等完善,写脚本可以用的上
thetbw
2021-08-24 14:20:53 +08:00
已 start ,其实对于这种小框架,感觉支持 sqlite 或者 h2 还是蛮不错了,毕竟都很轻量
xgfan
2021-08-24 14:48:08 +08:00
好奇和 exposed 相比,有啥卖点吗?
actar
2021-08-24 15:20:36 +08:00
@thetbw 可以考虑
actar
2021-08-24 15:25:50 +08:00
原来我是使用 JPA + QueryDSL 的,然后使用有些地方不顺手。本来是打算包装一下 QueryDSL 方便自己用的。看了一部分代码,然后产生了我上我也行的错觉。 😂
coderwl
2021-08-25 20:15:24 +08:00
直接 ktorm 不香吗
VincentLau
2021-08-30 15:53:55 +08:00
赞,不错

这是一个专为移动设备优化的页面(即为了让你能够在 Google 搜索结果里秒开这个页面),如果你希望参与 V2EX 社区的讨论,你可以继续到 V2EX 上打开本讨论主题的完整版本。

https://www.v2ex.com/t/797518

V2EX 是创意工作者们的社区,是一个分享自己正在做的有趣事物、交流想法,可以遇见新朋友甚至新机会的地方。

V2EX is a community of developers, designers and creative people.

© 2021 V2EX