抱歉,您的浏览器无法访问本站

本页面需要浏览器支持(启用)JavaScript


了解详情 >

Ktorm 是直接基于纯 JDBC 编写的高效简洁的轻量级 Kotlin ORM 框架,它提供了强类型而且灵活的 SQL DSL 和方便的序列 API,本文讲述如何在Quarkus中使用Ktorm

快速开始

1.引入依赖

    // quarkus resteasy依赖,建议使用jackson
    implementation("io.quarkus:quarkus-resteasy-reactive-jackson")

    // ktorm依赖
    implementation("org.ktorm:ktorm-core:${ktOrmVersion}")
    implementation("org.ktorm:ktorm-support-mysql:${ktOrmVersion}")

    // 如不需要连接池可不引入,也可替换为其他连接池如Druid
    // https://github.com/brettwooldridge/HikariCP
    implementation("com.zaxxer:HikariCP:5.0.1")

2.配置数据源

quarkus.datasource.jdbc.url=jdbc:mysql://127.0.0.1:3306/test
quarkus.datasource.username=root
quarkus.datasource.password=root

3.配置类

class KtOrmConfiguration {
    @ConfigProperty(name = "quarkus.datasource.jdbc.url")
    lateinit var url: String

    @ConfigProperty(name = "quarkus.datasource.username")
    lateinit var username: String

    @ConfigProperty(name = "quarkus.datasource.password")
    lateinit var password: String

    @ApplicationScoped
    fun database(): Database {
        // 不需要数据源可直接返回
        // return  Database.connect(url,"com.mysql.jdbc.Driver",username,password)

        val config = HikariConfig()
        config.jdbcUrl = url
        config.username = username
        config.password = password
        config.maxLifetime = 120000
        return Database.connect(HikariDataSource(config))
    }
}

4.创建表结构

object Employees : Table<Nothing>("t_employee") {
    val id = int("id").primaryKey()
    val name = varchar("name")
    val job = varchar("job")
    val managerId = int("manager_id")
    val hireDate = date("hire_date")
    val salary = long("salary")
    val departmentId = int("department_id")
}

5.使用

可在任意位置通过 @Inject 注入直接使用

    @Inject
    lateinit var database: Database

    func test(){
      for (row in database.from(Employees).select()) {
        println(row[Employees.name])
      }
    }

实体类与列绑定

1.定义实体类

// 实体类建议采用interface
// 更多信息可查看https://www.ktorm.org/zh-cn/entities-and-column-binding.html
interface User : Entity<User> {
    companion object : Entity.Factory<User>()

    var id: Long
    var avatarUrl: String
    var nickName: String
}

object Users : Table<User>("user") {
    val id = long("id").primaryKey().bindTo { it.id }
    val avatarUrl = varchar("avatar_url").bindTo { it.avatarUrl }
    val nickName = varchar("nick_name").bindTo { it.nickName }
}

2.查询

// 查询出来为List<User>
val userList = database.sequenceOf(Users).toList()

3.序列化

此时如果在接口处返回User类是无法正常序列化的,需要给 jackson 注册ktorm-jackson序列化模块

  • 引入依赖
      implementation("org.ktorm:ktorm-jackson:${ktOrmVersion}")
    
  • 注册模块
    @Singleton
    class RegisterCustomModuleCustomizer : ObjectMapperCustomizer {
      override fun customize(mapper: ObjectMapper) {
          mapper.registerModule(KtormModule())
      }
    }
    

通用Service

1.增加BaseService

/**
 * Created by vince on Jun 15, 2022.
 */
abstract class BaseService<E : Entity<E>, T : Table<E>>(private val tableObject: T) {
    @Inject
    protected lateinit var database: Database

    /**
     * Insert the given entity into the table and return the effected record number.
     */
    open fun add(entity: E): Int {
        return database.sequenceOf(tableObject).add(entity)
    }

    /**
     * Update properties of the given entity to the table and return the effected record number.
     */
    open fun update(entity: E): Int {
        return database.sequenceOf(tableObject).update(entity)
    }

    /**
     * Delete records that satisfy the given [predicate].
     */
    open fun deleteIf(predicate: (T) -> ColumnDeclaring<Boolean>): Int {
        return database.sequenceOf(tableObject).removeIf(predicate)
    }

    /**
     * Return true if all records match the given [predicate].
     */
    open fun allMatched(predicate: (T) -> ColumnDeclaring<Boolean>): Boolean {
        return database.sequenceOf(tableObject).all(predicate)
    }

    /**
     * Return true if at least one record match the given [predicate].
     */
    open fun anyMatched(predicate: (T) -> ColumnDeclaring<Boolean>): Boolean {
        return database.sequenceOf(tableObject).any(predicate)
    }

    /**
     * Return true if no records match the given [predicate].
     */
    open fun noneMatched(predicate: (T) -> ColumnDeclaring<Boolean>): Boolean {
        return database.sequenceOf(tableObject).none(predicate)
    }

    /**
     * Return the number of records in the table.
     */
    open fun count(): Int {
        return database.sequenceOf(tableObject).count()
    }

    /**
     * Return the number of records matching the given [predicate] in the table.
     */
    open fun count(predicate: (T) -> ColumnDeclaring<Boolean>): Int {
        return database.sequenceOf(tableObject).count(predicate)
    }

    /**
     * Return an entity object matching the given [predicate].
     */
    open fun findOne(predicate: (T) -> ColumnDeclaring<Boolean>): E? {
        return database.sequenceOf(tableObject).find(predicate)
    }

    /**
     * Return a list of entities matching the given [predicate].
     */
    open fun findList(predicate: (T) -> ColumnDeclaring<Boolean>): List<E> {
        return database.sequenceOf(tableObject).filter(predicate).toList()
    }

    /**
     * Return all entities in the table.
     */
    open fun findAll(): List<E> {
        return database.sequenceOf(tableObject).toList()
    }
}

2.编写UserService

User 为例,其他表也添加相应 xxxService 即可

@ApplicationScoped
class UserService : BaseService<User, Users>(Users) {
}

3.使用

@Path("/user")
class UserResource {
    @Inject
    lateinit var userService: UserService

    @GET
    fun getOne(): User? {
        return userService.findOne { Users.id eq 1 }
    }

评论