掘金 后端 ( ) • 2024-05-03 09:56

仓库地址:

github

gitee

背景

日后 ktorm-extend 将以插件的形式在ktorm的基础上进行简单的扩展

Ktorm是Kotlin的原生ORM框架,目前最新版本为3.6.0,本扩展插件在Ktorm的基础上进行简单扩展,添加了对Solon框架的事务支持,同时支持了Ktorm的分页查询函数和对Ktorm的事务函数做了简单的函数封装。

其实主要是我自己在开发过程中想要封装一些常用的函数,所以就写了这个扩展插件。

1.Solon事务支持

Solon是一个Java “生态型”应用开发框架。从零开始构建,有自主的标准规范与开放生态。目前已经通过了开放原子基金会的认证,成为了开放原子基金会的孵化项目。 作者 noear(西东)是一位多产型开源作者。

Ktorm本身支持Spring的事务托管,但是缺乏对于第三方的具有本身事务管理体系的框架的支持,所以本扩展插件添加了Solon框架的事务支持。由于Ktorm本身提供了事务扩展的可能性,所以理论上可以参考Spring的事务委托方式实现对于所有“生态型”框架的原生支持。 本扩展仿照Spring的事务方式,添加了Solon框架的事务支持。

使用以下函数可以实现Solon的事务委托。

Database.connectWithSolonSupport(dataSource)

启用Solon委托之后,就只能使用@Tran注解来使用事务了,并且该函数仅支持Solon 2.7.4+的版本。

2.7.4以下的版本请使用Ktorm默认的连接创建方式,如果想要使用注解是事务管理,可以使用@SolonTransaction来实现, 该注解是通过Solon的AOP特性来实现的,具体请参考 KtormInterceptor.kt

具体实现请参考如 SolonTransactionManager.kt

2.事务封装函数

fun <R> transaction(
    database: Database,
    transactionType: Int = DEFAULT,
    isolation: TransactionIsolation? = null,
    func: (Database) -> R
): R {
    contract {
        callsInPlace(func, InvocationKind.EXACTLY_ONCE)
    }
    return when (transactionType) {
        NEW -> nextTransactionManager(database.transactionManager, isolation) {
            func(database)
        }

        DEFAULT -> currentTransactionManager(database, isolation, func)
        else -> throw UnsupportedOperationException("The current transaction creation type is not supported")
    }

}

通过传递Database和事务类型transactionType以及事务隔离级别来实现的,默认情况下会使用当前的事务,如果事务类型声明为NEW,则会创建一个新的事务来执行。

 fun insert() {
    transaction(database) {
        val department = Department {
            this.departmentNumber = "1"
            this.name = "开发部"
            this.parentId = 0
        }
        database.departments.add(department)
    }
}

注意:DataBase参数是必须传递的,因为封装的底层仍然是通过Ktorm的事务函数来实现的,仅仅是做了上层封装,所以需要传递一个DataBase对象。 请参考KtranFunction.kt

封装的事务函数和@SolonTransaction的底层实现是想通的。

3.Ktorm的扩展操作函数

  • 数据存在判断函数
    //存在判断
    fun <E : Any, T : BaseTable<E>> EntitySequence<E, T>.exist(
        predicate: (T) -> ColumnDeclaring<Boolean>
    ): Boolean {
        return this.filter(predicate).isNotEmpty()
    }
    //不存在判断
    fun <E : Any, T : BaseTable<E>> EntitySequence<E, T>.noExist(
      predicate: (T) -> ColumnDeclaring<Boolean>
    ): Boolean {
      return this.filter(predicate).isEmpty()
    }
  • 分页查询函数
   /**
     *  EntitySequence的分页查询,最终返回仍然是一个EntitySequence
     *
     */

    fun <E : Any, T : BaseTable<E>> EntitySequence<E, T>.page(page: Int, pageSiz: Int): EntitySequence<E, T> {
        return this.withExpression(expression.copy(limit = pageSiz, offset = page * pageSiz))
    }

    /**
     *  EntitySequence的分页查询,最终返回仍然是一个EntitySequence
     *  此函数传入的[page]会直接进行减一操作
     *
     */
    fun <E : Any, T : BaseTable<E>> EntitySequence<E, T>.page0(page: Int, pageSiz: Int): EntitySequence<E, T> {
        return this.withExpression(expression.copy(limit = pageSiz, offset = (page - 1) * pageSiz))
    }


    /**
     * 返回Query的分页,返回Query
     */

     fun Query.page(page: Int, pageSiz: Long): Query {
        return this.limit((pageSiz * page).toInt(), pageSiz.toInt())
    }

    /**
     * 返回Query的分页,返回Query
     * 此函数传入的[page]会直接进行减一操作
     */
    fun Query.page0(page: Int, pageSiz: Long): Query {
        return this.limit((pageSiz * page - 1).toInt(), pageSiz.toInt())
    }