From 7fa117e0ac55a858e3c8d7a23a53ad55c7ed3643 Mon Sep 17 00:00:00 2001
From: kamosama <837080904@qq.com>
Date: Mon, 7 Aug 2023 21:59:09 +0800
Subject: [PATCH] feat: Extensions for Kotlin
---
mybatis-flex-kotlin/pom.xml | 112 ++++
.../com/mybatisflex/kotlin/db/DbConfig.kt | 37 ++
.../com/mybatisflex/kotlin/entry/Entry.kt | 49 ++
.../mybatisflex/kotlin/extend/db/DbExtend.kt | 588 ++++++++++++++++++
.../kotlin/extend/entry/EntryExtend.kt | 85 +++
.../kotlin/extend/mapper/MaaperExtend.kt | 22 +
.../kotlin/extend/sql/SqlExtend.kt | 59 ++
.../mybatisflex/kotlin/scope/QueryScope.kt | 45 ++
.../mybatisflex/kotlintest/ExtensionTest.kt | 76 +++
.../mybatisflex/kotlintest/entry/Account.kt | 25 +
.../src/test/resources/data.sql | 4 +
.../test/resources/mybatis-flex.properties | 4 +
.../src/test/resources/schema.sql | 15 +
pom.xml | 1 +
14 files changed, 1122 insertions(+)
create mode 100755 mybatis-flex-kotlin/pom.xml
create mode 100644 mybatis-flex-kotlin/src/main/java/com/mybatisflex/kotlin/db/DbConfig.kt
create mode 100644 mybatis-flex-kotlin/src/main/java/com/mybatisflex/kotlin/entry/Entry.kt
create mode 100644 mybatis-flex-kotlin/src/main/java/com/mybatisflex/kotlin/extend/db/DbExtend.kt
create mode 100644 mybatis-flex-kotlin/src/main/java/com/mybatisflex/kotlin/extend/entry/EntryExtend.kt
create mode 100644 mybatis-flex-kotlin/src/main/java/com/mybatisflex/kotlin/extend/mapper/MaaperExtend.kt
create mode 100644 mybatis-flex-kotlin/src/main/java/com/mybatisflex/kotlin/extend/sql/SqlExtend.kt
create mode 100755 mybatis-flex-kotlin/src/main/java/com/mybatisflex/kotlin/scope/QueryScope.kt
create mode 100755 mybatis-flex-kotlin/src/test/java/com/mybatisflex/kotlintest/ExtensionTest.kt
create mode 100755 mybatis-flex-kotlin/src/test/java/com/mybatisflex/kotlintest/entry/Account.kt
create mode 100755 mybatis-flex-kotlin/src/test/resources/data.sql
create mode 100755 mybatis-flex-kotlin/src/test/resources/mybatis-flex.properties
create mode 100755 mybatis-flex-kotlin/src/test/resources/schema.sql
diff --git a/mybatis-flex-kotlin/pom.xml b/mybatis-flex-kotlin/pom.xml
new file mode 100755
index 00000000..08d61f65
--- /dev/null
+++ b/mybatis-flex-kotlin/pom.xml
@@ -0,0 +1,112 @@
+
+
+ 4.0.0
+
+ com.mybatis-flex
+ parent
+ 1.4.8
+
+
+ mybatis-flex-kotlin
+
+
+ 8
+ 8
+ UTF-8
+ 1.9.0
+
+
+
+
+ com.mybatis-flex
+ mybatis-flex-core
+ 1.4.8
+
+
+ org.jetbrains.kotlin
+ kotlin-test
+ ${kotlin.version}
+ test
+
+
+ org.jetbrains.kotlin
+ kotlin-stdlib-jdk8
+ ${kotlin.version}
+ compile
+
+
+ org.testng
+ testng
+ 7.7.1
+ test
+
+
+ org.springframework
+ spring-jdbc
+ test
+
+
+ com.h2database
+ h2
+ 2.1.214
+ test
+
+
+
+
+
+
+
+ org.jetbrains.kotlin
+ kotlin-maven-plugin
+ ${kotlin.version}
+
+ 1.8
+
+ -Xjvm-default=all
+
+
+
+
+ kapt
+
+ kapt
+
+
+
+ src/main/kotlin
+ src/main/java
+
+
+
+
+ com.google.dagger
+ dagger-compiler
+ 2.9
+
+
+
+
+
+ compile
+ process-sources
+
+ compile
+
+
+
+ test-compile
+ test-compile
+
+ test-compile
+
+
+
+
+
+
+
+
+
diff --git a/mybatis-flex-kotlin/src/main/java/com/mybatisflex/kotlin/db/DbConfig.kt b/mybatis-flex-kotlin/src/main/java/com/mybatisflex/kotlin/db/DbConfig.kt
new file mode 100644
index 00000000..c10dca34
--- /dev/null
+++ b/mybatis-flex-kotlin/src/main/java/com/mybatisflex/kotlin/db/DbConfig.kt
@@ -0,0 +1,37 @@
+package com.mybatisflex.kotlin.db
+
+import kotlin.properties.ReadWriteProperty
+import kotlin.reflect.KProperty
+/**
+ * 数据库配置对象,暂时未启用
+ * @author 卡莫sama(yuanjiashuai)
+ * @date 2023/8/7
+ */
+object DbConfig {
+
+ var url: String by IfNullVar { "" }
+ var username: String by IfNullVar { "" }
+ var password: String by IfNullVar { "" }
+
+
+}
+
+class IfNullVar(private var init: (() -> T)?) : ReadWriteProperty {
+ private var _value: T? = null
+
+ override fun getValue(thisRef: Any?, property: KProperty<*>): T {
+ if (_value == null) {
+ synchronized(this) {
+ if (_value == null) {
+ _value = init!!()
+ init = null
+ }
+ }
+ }
+ return this._value!!
+ }
+
+ override fun setValue(thisRef: Any?, property: KProperty<*>, value: T) {
+ _value = value
+ }
+}
diff --git a/mybatis-flex-kotlin/src/main/java/com/mybatisflex/kotlin/entry/Entry.kt b/mybatis-flex-kotlin/src/main/java/com/mybatisflex/kotlin/entry/Entry.kt
new file mode 100644
index 00000000..2e48c5e9
--- /dev/null
+++ b/mybatis-flex-kotlin/src/main/java/com/mybatisflex/kotlin/entry/Entry.kt
@@ -0,0 +1,49 @@
+package com.mybatisflex.kotlin.entry
+
+import com.mybatisflex.core.dialect.DialectFactory
+import com.mybatisflex.core.table.TableInfoFactory
+import com.mybatisflex.core.util.ArrayUtil
+import com.mybatisflex.kotlin.extend.db.DB
+import java.io.Serializable
+/**
+ * 实体类父类,继承该类后将赋予实体简单增删改操作
+ * @author 卡莫sama(yuanjiashuai)
+ * @date 2023/8/7
+ */
+open class Entry :Serializable{
+
+ fun save(ignoreNulls: Boolean = true): Boolean {
+ val tableInfo = TableInfoFactory.ofEntityClass(this.javaClass)
+ //设置乐观锁版本字段的初始化数据
+ tableInfo.initVersionValueIfNecessary(this)
+ //设置租户ID
+ tableInfo.initTenantIdIfNecessary(this)
+ //设置逻辑删除字段的出初始化数据
+ tableInfo.initLogicDeleteValueIfNecessary(this)
+ //执行 onInsert 监听器
+ tableInfo.invokeOnInsertListener(this)
+ val values = tableInfo.buildInsertSqlArgs(this, ignoreNulls)
+ val sql = DialectFactory.getDialect().forInsertEntity(tableInfo, this, ignoreNulls)
+ return DB.insertBySql(sql, *values) == 1
+ }
+
+ fun update(ignoreNulls: Boolean = true): Boolean {
+ val tableInfo = TableInfoFactory.ofEntityClass(this.javaClass)
+ //执行 onUpdate 监听器
+ tableInfo.invokeOnUpdateListener(this)
+ val updateValues = tableInfo.buildUpdateSqlArgs(this, ignoreNulls, false)
+ val primaryValues = tableInfo.buildPkSqlArgs(this)
+ val tenantIdArgs = tableInfo.buildTenantIdArgs()
+ val sql = DialectFactory.getDialect().forUpdateEntity(tableInfo, this, ignoreNulls)
+ return DB.updateBySql(sql, *ArrayUtil.concat(updateValues, primaryValues, tenantIdArgs)) == 1
+ }
+
+ fun deleteById(): Boolean {
+ val tableInfo = TableInfoFactory.ofEntityClass(this.javaClass)
+ val primaryValues = tableInfo.buildPkSqlArgs(this)
+ val allValues = ArrayUtil.concat(primaryValues, tableInfo.buildTenantIdArgs())
+ val sql = DialectFactory.getDialect().forDeleteEntityById(tableInfo)
+ return DB.deleteBySql(sql, *allValues) == 1
+ }
+
+}
diff --git a/mybatis-flex-kotlin/src/main/java/com/mybatisflex/kotlin/extend/db/DbExtend.kt b/mybatis-flex-kotlin/src/main/java/com/mybatisflex/kotlin/extend/db/DbExtend.kt
new file mode 100644
index 00000000..ecde6b81
--- /dev/null
+++ b/mybatis-flex-kotlin/src/main/java/com/mybatisflex/kotlin/extend/db/DbExtend.kt
@@ -0,0 +1,588 @@
+package com.mybatisflex.kotlin.extend.db
+
+import com.mybatisflex.core.BaseMapper
+import com.mybatisflex.core.MybatisFlexBootstrap
+import com.mybatisflex.core.paginate.Page
+import com.mybatisflex.core.query.QueryColumn
+import com.mybatisflex.core.query.QueryCondition
+import com.mybatisflex.core.query.QueryWrapper
+import com.mybatisflex.core.row.*
+import com.mybatisflex.core.table.TableDef
+import com.mybatisflex.core.table.TableInfoFactory
+import com.mybatisflex.core.transaction.Propagation
+import com.mybatisflex.kotlin.extend.entry.filter
+import com.mybatisflex.kotlin.extend.entry.toEntities
+import com.mybatisflex.kotlin.scope.QueryScope
+import com.mybatisflex.kotlin.scope.queryScope
+import java.util.function.BiConsumer
+import java.util.function.Supplier
+
+/**
+ * 数据库操作对象
+ * @author 卡莫sama(yuanjiashuai)
+ * @date 2023/8/7
+ */
+object DB {
+
+ fun invoker(): RowMapperInvoker = Db.invoker()
+
+ fun invoker(environmentId: String): RowMapperInvoker = Db.invoker(environmentId)
+
+ inline fun > mapper(): M = MybatisFlexBootstrap.getInstance().getMapper(M::class.java)
+
+ inline fun queryOne(
+ vararg columns: QueryColumn,
+ schema: String? = null,
+ tableName: String? = null,
+ noinline init: QueryScope.() -> Unit
+ ): T = queryRow(schema = schema, tableName = tableName, columns = columns, init = init).toEntity(T::class.java)
+
+
+ fun queryRow(
+ vararg columns: QueryColumn?,
+ schema: String? = null,
+ tableName: String? = null,
+ init: QueryScope.() -> Unit
+ ): Row =
+ selectOneByQuery(
+ schema = schema,
+ tableName = tableName,
+ queryWrapper = queryScope(columns = columns, init = init)
+ )
+
+
+ inline fun query(
+ vararg columns: QueryColumn?,
+ schema: String? = null,
+ tableName: String? = null,
+ noinline init: QueryScope.() -> Unit
+ ): List =
+ queryRows(schema = schema, tableName = tableName, columns = columns, init = init)
+ .toEntities()
+
+ fun queryRows(
+ vararg columns: QueryColumn?,
+ schema: String? = null,
+ tableName: String? = null,
+ init: QueryScope.() -> Unit
+ ): List = selectListByQuery(
+ schema = schema, tableName = tableName,
+ queryWrapper = queryScope(columns = columns, init = init)
+ )
+
+ // filter-----------
+ inline fun filter(
+ tableName: String,
+ schema: String,
+ vararg columns: QueryColumn?,
+ queryCondition: QueryCondition = QueryCondition.createEmpty()
+ ): List = selectListByQuery(
+ schema,
+ tableName,
+ queryScope(*columns).where(queryCondition)
+ ).toEntities()
+
+ inline fun filter(
+ vararg columns: QueryColumn?,
+ init: () -> QueryCondition
+ ): List {
+ val tableInfo = TableInfoFactory.ofEntityClass(E::class.java)
+ return filter(
+ columns = columns,
+ schema = tableInfo.schema,
+ tableName = tableInfo.tableName,
+ queryCondition = init()
+ )
+ }
+
+ inline fun filter(
+ tableDef: T,
+ vararg columns: QueryColumn?,
+ init: T.() -> QueryCondition
+ ): List = tableDef.filter(columns = columns, init = init)
+
+
+ // ----------------------
+ fun insert(schema: String?, tableName: String?, row: Row?): Int {
+ return Db.insert(schema, tableName, row)
+ }
+
+ fun insert(tableName: String?, row: Row?): Int {
+ return Db.insert(null as String?, tableName, row)
+ }
+
+ fun insertBySql(sql: String?, vararg args: Any?): Int {
+ return Db.insertBySql(sql, *args)
+ }
+
+ fun insertBatch(schema: String?, tableName: String?, rows: Collection): IntArray {
+ return insertBatch(schema, tableName, rows, rows.size)
+ }
+
+ fun insertBatch(tableName: String?, rows: Collection): IntArray {
+ return insertBatch(null as String?, tableName, rows, rows.size)
+ }
+
+ fun insertBatch(schema: String?, tableName: String?, rows: Collection, batchSize: Int): IntArray {
+ return Db.insertBatch(schema, tableName, rows, batchSize)
+ }
+
+ fun insertBatch(tableName: String?, rows: Collection, batchSize: Int): IntArray {
+ return Db.insertBatch(tableName, rows)
+ }
+
+ fun insertBatchWithFirstRowColumns(schema: String?, tableName: String?, rows: List?): Int {
+ return Db.insertBatchWithFirstRowColumns(schema, tableName, rows)
+ }
+
+ fun insertBatchWithFirstRowColumns(tableName: String?, rows: List?): Int {
+ return Db.insertBatchWithFirstRowColumns(null as String?, tableName, rows)
+ }
+
+ fun deleteBySql(sql: String?, vararg args: Any?): Int {
+ return Db.deleteBySql(sql, *args)
+ }
+
+ fun deleteById(schema: String?, tableName: String?, row: Row?): Int {
+ return Db.deleteById(schema, tableName, row)
+ }
+
+ fun deleteById(tableName: String?, row: Row?): Int {
+ return Db.deleteById(null as String?, tableName, row)
+ }
+
+ fun deleteById(schema: String?, tableName: String?, primaryKey: String?, id: Any?): Int {
+ return Db.deleteById(schema, tableName, primaryKey, id)
+ }
+
+ fun deleteById(tableName: String?, primaryKey: String?, id: Any?): Int {
+ return Db.deleteById(null as String?, tableName, primaryKey, id)
+ }
+
+ fun deleteBatchByIds(schema: String?, tableName: String?, primaryKey: String?, ids: Collection<*>?): Int {
+ return Db.deleteBatchByIds(schema, tableName, primaryKey, ids)
+ }
+
+ fun deleteBatchByIds(tableName: String?, primaryKey: String?, ids: Collection<*>?): Int {
+ return Db.deleteBatchByIds(null as String?, tableName, primaryKey, ids)
+ }
+
+ fun deleteByMap(schema: String?, tableName: String?, whereColumns: Map?): Int {
+ return Db.deleteByQuery(
+ schema, tableName, QueryWrapper()
+ .where(whereColumns)
+ )
+ }
+
+ fun deleteByMap(tableName: String?, whereColumns: Map?): Int {
+ return Db.deleteByQuery(
+ null as String?, tableName, QueryWrapper()
+ .where(whereColumns)
+ )
+ }
+
+ fun deleteByCondition(schema: String?, tableName: String?, condition: QueryCondition?): Int {
+ return Db.deleteByQuery(
+ schema, tableName, QueryWrapper()
+ .where(condition)
+ )
+ }
+
+ fun deleteByCondition(tableName: String?, condition: QueryCondition?): Int {
+ return Db.deleteByQuery(
+ null as String?, tableName, QueryWrapper()
+ .where(condition)
+ )
+ }
+
+ fun deleteByQuery(schema: String?, tableName: String?, queryWrapper: QueryWrapper?): Int {
+ return Db.deleteByQuery(schema, tableName, queryWrapper)
+ }
+
+ fun deleteByQuery(tableName: String?, queryWrapper: QueryWrapper?): Int {
+ return Db.deleteByQuery(null as String?, tableName, queryWrapper)
+ }
+
+ fun updateBySql(sql: String?, vararg args: Any?): Int {
+ return Db.updateBySql(sql, *args)
+ }
+
+ fun updateBatch(sql: String?, batchArgsSetter: BatchArgsSetter): IntArray {
+ return Db.updateBatch(sql, batchArgsSetter)
+ }
+
+
+ fun updateById(schema: String?, tableName: String?, row: Row?): Int {
+ return Db.updateById(schema, tableName, row)
+ }
+
+ fun updateById(tableName: String?, row: Row?): Int {
+ return Db.updateById(null as String?, tableName, row)
+ }
+
+ fun updateByMap(schema: String?, tableName: String?, data: Row?, whereColumns: Map?): Int {
+ return Db.updateByQuery(
+ schema, tableName, data, QueryWrapper()
+ .where(whereColumns)
+ )
+ }
+
+ fun updateByMap(tableName: String?, data: Row?, whereColumns: Map?): Int {
+ return Db.updateByQuery(
+ null as String?, tableName, data, QueryWrapper()
+ .where(whereColumns)
+ )
+ }
+
+ fun updateByCondition(schema: String?, tableName: String?, data: Row?, condition: QueryCondition?): Int {
+ return Db.updateByQuery(
+ schema, tableName, data, QueryWrapper()
+ .where(condition)
+ )
+ }
+
+ fun updateByCondition(tableName: String?, data: Row?, condition: QueryCondition?): Int {
+ return Db.updateByQuery(
+ null as String?, tableName, data, QueryWrapper()
+ .where(condition)
+ )
+ }
+
+ fun updateByQuery(schema: String?, tableName: String?, data: Row?, queryWrapper: QueryWrapper?): Int {
+ return Db.updateByQuery(schema, tableName, data, queryWrapper)
+ }
+
+ fun updateByQuery(tableName: String?, data: Row?, queryWrapper: QueryWrapper?): Int {
+ return Db.updateByQuery(null as String?, tableName, data, queryWrapper)
+ }
+
+ fun updateBatchById(schema: String?, tableName: String?, rows: List?): Int {
+ return Db.updateBatchById(schema, tableName, rows)
+ }
+
+ fun updateBatchById(tableName: String?, rows: List?): Int {
+ return Db.updateBatchById(null as String?, tableName, rows)
+ }
+
+ fun updateEntitiesBatch(entities: Collection?, batchSize: Int): Int {
+ return Db.updateEntitiesBatch(entities, batchSize)
+ }
+
+ fun updateEntitiesBatch(entities: Collection?): Int {
+ return updateEntitiesBatch(entities, 1000)
+ }
+
+ fun updateNumberAddByQuery(
+ schema: String?,
+ tableName: String?,
+ fieldName: String?,
+ value: Number?,
+ queryWrapper: QueryWrapper?
+ ): Int {
+ return Db.updateNumberAddByQuery(schema, tableName, fieldName, value, queryWrapper)
+ }
+
+ fun updateNumberAddByQuery(
+ tableName: String?,
+ fieldName: String?,
+ value: Number?,
+ queryWrapper: QueryWrapper?
+ ): Int {
+ return Db.updateNumberAddByQuery(null as String?, tableName, fieldName, value, queryWrapper)
+ }
+
+ fun executeBatch(
+ totalSize: Int,
+ batchSize: Int,
+ mapperClass: Class?,
+ consumer: BiConsumer?
+ ): IntArray {
+ return Db.executeBatch(totalSize, batchSize, mapperClass, consumer)
+ }
+
+ fun selectOneBySql(sql: String?, vararg args: Any?): Row {
+ return Db.selectOneBySql(sql, *args)
+ }
+
+
+ fun selectOneById(schema: String?, tableName: String?, row: Row?): Row {
+ return Db.selectOneById(schema, tableName, row)
+ }
+
+ fun selectOneById(tableName: String?, row: Row?): Row {
+ return Db.selectOneById(null as String?, tableName, row)
+ }
+
+ fun selectOneById(schema: String?, tableName: String?, primaryKey: String?, id: Any?): Row {
+ return Db.selectOneById(schema, tableName, primaryKey, id)
+ }
+
+ fun selectOneById(tableName: String?, primaryKey: String?, id: Any?): Row {
+ return Db.selectOneById(null as String?, tableName, primaryKey, id)
+ }
+
+ fun selectOneByMap(schema: String?, tableName: String?, whereColumns: Map?): Row {
+ return Db.selectOneByQuery(
+ schema, tableName, QueryWrapper()
+ .where(whereColumns).limit(1)
+ )
+ }
+
+ fun selectOneByMap(tableName: String?, whereColumns: Map?): Row {
+ return Db.selectOneByQuery(
+ null as String?, tableName, QueryWrapper().where(whereColumns).limit(1)
+ )
+ }
+
+ fun selectOneByCondition(schema: String?, tableName: String?, condition: QueryCondition?): Row {
+ return Db.selectOneByQuery(
+ schema, tableName, QueryWrapper()
+ .where(condition).limit(1)
+ )
+ }
+
+ fun selectOneByCondition(tableName: String?, condition: QueryCondition?): Row {
+ return Db.selectOneByQuery(
+ null as String?, tableName, QueryWrapper()
+ .where(condition).limit(1)
+ )
+ }
+
+ fun selectOneByQuery(schema: String?, tableName: String?, queryWrapper: QueryWrapper?): Row {
+ return Db.selectOneByQuery(schema, tableName, queryWrapper)
+ }
+
+ fun selectOneByQuery(tableName: String?, queryWrapper: QueryWrapper?): Row {
+ return Db.selectOneByQuery(null as String?, tableName, queryWrapper)
+ }
+
+ fun selectOneByQuery(queryWrapper: QueryWrapper?): Row {
+ return Db.selectOneByQuery(queryWrapper)
+ }
+
+ fun selectListBySql(sql: String?, vararg args: Any?): List {
+ return Db.selectListBySql(sql, *args)
+ }
+
+ fun selectListByMap(schema: String?, tableName: String?, whereColumns: Map?): List {
+ return Db.selectListByQuery(
+ schema, tableName, QueryWrapper()
+ .where(whereColumns)
+ )
+ }
+
+ fun selectListByMap(tableName: String?, whereColumns: Map?): List {
+ return Db.selectListByMap(tableName, whereColumns)
+ }
+
+ fun selectListByMap(schema: String?, tableName: String?, whereColumns: Map?, count: Int): List {
+ return Db.selectListByMap(schema, tableName, whereColumns, count)
+ }
+
+ fun selectListByMap(tableName: String?, whereColumns: Map?, count: Int): List {
+ return Db.selectListByMap(tableName, whereColumns, count)
+ }
+
+ fun selectListByCondition(schema: String?, tableName: String?, condition: QueryCondition?): List {
+ return Db.selectListByCondition(schema, tableName, condition)
+ }
+
+ fun selectListByCondition(tableName: String?, condition: QueryCondition?): List {
+ return Db.selectListByQuery(
+ null as String?, tableName, QueryWrapper()
+ .where(condition)
+ )
+ }
+
+ fun selectListByCondition(schema: String?, tableName: String?, condition: QueryCondition?, count: Int): List {
+ return Db.selectListByQuery(
+ schema, tableName, QueryWrapper()
+ .where(condition).limit(count)
+ )
+ }
+
+ fun selectListByCondition(tableName: String?, condition: QueryCondition?, count: Int): List {
+ return Db.selectListByQuery(
+ null as String?, tableName, QueryWrapper()
+ .where(condition).limit(count)
+ )
+ }
+
+ fun selectListByQuery(schema: String?, tableName: String?, queryWrapper: QueryWrapper?): List {
+ return Db.selectListByQuery(schema, tableName, queryWrapper)
+ }
+
+ fun selectListByQuery(tableName: String?, queryWrapper: QueryWrapper?): List {
+ return Db.selectListByQuery(null as String?, tableName, queryWrapper)
+ }
+
+ fun selectListByQuery(queryWrapper: QueryWrapper?): List {
+ return Db.selectListByQuery(queryWrapper)
+ }
+
+ fun selectAll(schema: String?, tableName: String?): List {
+ return Db.selectAll(schema, tableName)
+ }
+
+ fun selectAll(tableName: String?): List {
+ return Db.selectAll(null as String?, tableName)
+ }
+
+ fun selectObject(sql: String?, vararg args: Any?): Any {
+ return Db.selectObject(sql, *args)
+ }
+
+ fun selectObject(schema: String?, tableName: String?, queryWrapper: QueryWrapper?): Any {
+ return Db.selectObject(schema, tableName, queryWrapper)
+ }
+
+ fun selectObject(tableName: String?, queryWrapper: QueryWrapper?): Any {
+ return Db.selectObject(null as String?, tableName, queryWrapper)
+ }
+
+ fun selectObject(queryWrapper: QueryWrapper?): Any {
+ return Db.selectObject(queryWrapper)
+ }
+
+ fun selectObjectList(sql: String?, vararg args: Any?): List {
+ return Db.selectObjectList(sql, *args)
+ }
+
+ fun selectObjectList(schema: String?, tableName: String?, queryWrapper: QueryWrapper?): Any {
+ return Db.selectObjectList(schema, tableName, queryWrapper)
+ }
+
+ fun selectObjectList(tableName: String?, queryWrapper: QueryWrapper?): Any {
+ return Db.selectObjectList(tableName, queryWrapper)
+ }
+
+ fun selectObjectList(queryWrapper: QueryWrapper?): Any {
+ return Db.selectObjectList(queryWrapper)
+ }
+
+ fun selectCount(sql: String?, vararg args: Any?): Long {
+ return Db.selectCount(sql, *args)
+ }
+
+ fun selectCountByCondition(schema: String?, tableName: String?, condition: QueryCondition?): Long {
+ return Db.selectCountByQuery(
+ schema, tableName, QueryWrapper()
+ .where(condition)
+ )
+ }
+
+ fun selectCountByCondition(tableName: String?, condition: QueryCondition?): Long {
+ return Db.selectCountByCondition(
+ tableName, condition
+ )
+ }
+
+ fun selectCountByQuery(schema: String?, tableName: String?, queryWrapper: QueryWrapper?): Long {
+ return Db.selectCountByQuery(schema, tableName, queryWrapper)
+ }
+
+ fun selectCountByQuery(tableName: String?, queryWrapper: QueryWrapper?): Long {
+ return Db.selectCountByQuery(null as String?, tableName, queryWrapper)
+ }
+
+ fun selectCountByQuery(queryWrapper: QueryWrapper?): Long = Db.selectCountByQuery(queryWrapper)
+
+
+ fun paginate(
+ schema: String?,
+ tableName: String?,
+ pageNumber: Int,
+ pageSize: Int,
+ condition: QueryCondition?
+ ): Page = Db.paginate(schema, tableName, Page(pageNumber, pageSize), QueryWrapper.create().where(condition))
+
+
+ fun paginate(tableName: String?, pageNumber: Int, pageSize: Int, condition: QueryCondition?): Page =
+ Db.paginate(tableName, pageNumber, pageSize, condition)
+
+
+ fun paginate(
+ schema: String?,
+ tableName: String?,
+ pageNumber: Int,
+ pageSize: Int,
+ totalRow: Int,
+ condition: QueryCondition?
+ ): Page {
+ return Db.paginate(
+ schema, tableName, pageNumber, pageSize, totalRow, condition
+ )
+ }
+
+ fun paginate(
+ tableName: String?,
+ pageNumber: Int,
+ pageSize: Int,
+ totalRow: Int,
+ condition: QueryCondition?
+ ): Page = Db.paginate(tableName, pageNumber, pageSize, totalRow, condition)
+
+ fun paginate(
+ schema: String?,
+ tableName: String?,
+ pageNumber: Int,
+ pageSize: Int,
+ queryWrapper: QueryWrapper?
+ ): Page = Db.paginate(schema, tableName, pageNumber, pageSize, queryWrapper)
+
+ fun paginate(tableName: String?, pageNumber: Int, pageSize: Int, queryWrapper: QueryWrapper?): Page =
+ Db.paginate(tableName, pageNumber, pageSize, queryWrapper)
+
+ fun paginate(
+ schema: String?,
+ tableName: String?,
+ pageNumber: Int,
+ pageSize: Int,
+ totalRow: Int,
+ queryWrapper: QueryWrapper?
+ ): Page {
+ return Db
+ .paginate(schema, tableName, pageNumber, pageSize, totalRow, queryWrapper)
+ }
+
+ fun paginate(
+ tableName: String?,
+ pageNumber: Int,
+ pageSize: Int,
+ totalRow: Int,
+ queryWrapper: QueryWrapper?
+ ): Page {
+ return Db
+ .paginate(tableName, pageNumber, pageSize, totalRow, queryWrapper)
+ }
+
+ fun paginate(schema: String?, tableName: String?, page: Page?, queryWrapper: QueryWrapper?): Page {
+ return Db.paginate(schema, tableName, page, queryWrapper)
+ }
+
+ fun paginate(tableName: String?, page: Page?, queryWrapper: QueryWrapper?): Page {
+ return Db.paginate(tableName, page, queryWrapper)
+ }
+
+ fun tx(supplier: Supplier?): Boolean {
+ return tx(supplier, Propagation.REQUIRED)
+ }
+
+ fun tx(supplier: Supplier?, propagation: Propagation?): Boolean {
+ return Db.tx(supplier, propagation)
+ }
+
+ fun txWithResult(supplier: Supplier?): T {
+ return txWithResult(supplier, Propagation.REQUIRED)
+ }
+
+ fun txWithResult(supplier: Supplier?, propagation: Propagation?): T {
+ return Db.txWithResult(supplier, propagation)
+ }
+
+
+}
+
+
+
+
diff --git a/mybatis-flex-kotlin/src/main/java/com/mybatisflex/kotlin/extend/entry/EntryExtend.kt b/mybatis-flex-kotlin/src/main/java/com/mybatisflex/kotlin/extend/entry/EntryExtend.kt
new file mode 100644
index 00000000..c17321d8
--- /dev/null
+++ b/mybatis-flex-kotlin/src/main/java/com/mybatisflex/kotlin/extend/entry/EntryExtend.kt
@@ -0,0 +1,85 @@
+package com.mybatisflex.kotlin.extend.entry
+
+import com.mybatisflex.core.FlexConsts
+import com.mybatisflex.core.dialect.DialectFactory
+import com.mybatisflex.core.query.QueryColumn
+import com.mybatisflex.core.query.QueryCondition
+import com.mybatisflex.core.row.Row
+import com.mybatisflex.core.row.RowUtil
+import com.mybatisflex.core.table.TableDef
+import com.mybatisflex.core.table.TableInfoFactory
+import com.mybatisflex.core.util.ArrayUtil
+import com.mybatisflex.kotlin.entry.Entry
+import com.mybatisflex.kotlin.extend.db.DB
+import com.mybatisflex.kotlin.scope.QueryScope
+import java.util.Arrays
+
+/*
+ * 实体操作扩展
+ * @author 卡莫sama(yuanjiashuai)
+ * @date 2023/8/7
+ */
+
+infix fun Row.to(entryClass: Class): T {
+ return RowUtil.toEntity(this, entryClass)
+}
+
+inline fun T.filter(
+ vararg columns: QueryColumn?,
+ init: T.() -> QueryCondition
+): List {
+ val tableInfo = TableInfoFactory.ofEntityClass(E::class.java)
+ return DB.filter(
+ columns = columns,
+ schema = tableInfo.schema,
+ tableName = tableInfo.tableName,
+ queryCondition = init()
+ )
+}
+
+inline fun TableDef.query(
+ vararg columns: QueryColumn?,
+ noinline init: QueryScope.() -> Unit
+): List {
+ return DB.query(
+ columns = columns,
+ schema = this.schema,
+ tableName = this.tableName,
+ init = init
+ )
+}
+
+inline fun TableDef.all(
+ vararg columns: QueryColumn?
+): List = DB.selectAll(schema, tableName).toEntities()
+
+inline fun Collection.toEntities() = map { it to E::class.java }.toList()
+
+inline fun List.batchInsert(): Boolean {
+ val entities = this
+ val tableInfo = TableInfoFactory.ofEntityClass(E::class.java)
+ for (entity in entities) {
+ tableInfo.initVersionValueIfNecessary(entity)
+ tableInfo.initTenantIdIfNecessary(entity)
+ tableInfo.initLogicDeleteValueIfNecessary(entity)
+ //执行 onInsert 监听器
+ tableInfo.invokeOnInsertListener(entity)
+ }
+ var allValues = FlexConsts.EMPTY_ARRAY
+ for (entity in entities) {
+ allValues = ArrayUtil.concat(allValues, tableInfo.buildInsertSqlArgs(entity, false))
+ }
+ val sql = DialectFactory.getDialect().forInsertEntityBatch(tableInfo, entities)
+ return DB.insertBySql(sql,*allValues) > 1
+}
+
+
+fun< E:Entry> List.batchUpdate(): Boolean = all(Entry::update)
+
+inline fun List. batchDeleteById(): Boolean {
+ val tableInfo = TableInfoFactory.ofEntityClass(E::class.java)
+ val primaryValues = this.map { tableInfo.buildPkSqlArgs(it) }.stream().flatMap(Arrays::stream).toArray()
+ val tenantIdArgs = tableInfo.buildTenantIdArgs()
+ val sql = DialectFactory.getDialect().forDeleteEntityBatchByIds(tableInfo, primaryValues)
+ return DB.deleteBySql(sql,*ArrayUtil.concat(primaryValues, tenantIdArgs)) > 1
+}
diff --git a/mybatis-flex-kotlin/src/main/java/com/mybatisflex/kotlin/extend/mapper/MaaperExtend.kt b/mybatis-flex-kotlin/src/main/java/com/mybatisflex/kotlin/extend/mapper/MaaperExtend.kt
new file mode 100644
index 00000000..d14af29a
--- /dev/null
+++ b/mybatis-flex-kotlin/src/main/java/com/mybatisflex/kotlin/extend/mapper/MaaperExtend.kt
@@ -0,0 +1,22 @@
+package com.mybatisflex.kotlin.extend.mapper
+
+import com.mybatisflex.core.BaseMapper
+import com.mybatisflex.core.query.QueryCondition
+import com.mybatisflex.kotlin.scope.QueryScope
+import com.mybatisflex.kotlin.scope.queryScope
+/*
+ * 映射器操作扩展
+ * @author 卡莫sama(yuanjiashuai)
+ * @date 2023/8/7
+ */
+fun BaseMapper<*>.queryList(init: (QueryScope.() -> Unit)? = null): List =
+ this.selectListByQuery(queryScope(init = init)) as List
+
+fun BaseMapper.update(entity: T, init: () -> QueryCondition): Int =
+ this.updateByCondition(entity, init())
+
+fun BaseMapper.delete(init: (QueryScope.() -> Unit)? = null): Int =
+ this.deleteByQuery(queryScope(init = init))
+
+fun BaseMapper.delete1(init: () -> QueryCondition): Int =
+ this.deleteByCondition(init())
diff --git a/mybatis-flex-kotlin/src/main/java/com/mybatisflex/kotlin/extend/sql/SqlExtend.kt b/mybatis-flex-kotlin/src/main/java/com/mybatisflex/kotlin/extend/sql/SqlExtend.kt
new file mode 100644
index 00000000..3dc0e19b
--- /dev/null
+++ b/mybatis-flex-kotlin/src/main/java/com/mybatisflex/kotlin/extend/sql/SqlExtend.kt
@@ -0,0 +1,59 @@
+package com.mybatisflex.kotlin.extend.sql
+
+import com.mybatisflex.core.query.Joiner
+import com.mybatisflex.core.query.QueryColumn
+import com.mybatisflex.core.query.QueryCondition
+import com.mybatisflex.core.query.QueryWrapper
+import java.util.function.Consumer
+/*
+ * sql操作扩展
+ * @author 卡莫sama(yuanjiashuai)
+ * @date 2023/8/7
+ */
+infix fun QueryColumn.eq(value: Any?): QueryCondition {
+ return this.eq(value)
+}
+
+inline fun QueryCondition.andIf(test: Boolean, block: () -> QueryCondition): QueryCondition {
+ if (test) {
+ this.and(block())
+ }
+ return this
+}
+
+inline fun QueryCondition.orIf(test: Boolean, block: () -> QueryCondition): QueryCondition {
+ if (test) {
+ this.or(block())
+ }
+ return this
+}
+
+inline fun `if`(test: Boolean, block: () -> QueryCondition): QueryCondition {
+ if (test) {
+ return block()
+ }
+ return QueryCondition.createEmpty()
+}
+
+infix fun QueryColumn.like(value: String): QueryCondition = this.like(value)
+
+infix fun QueryCondition.and(other: QueryCondition): QueryCondition = this.and(other)
+
+infix fun QueryCondition.or(other: QueryCondition): QueryCondition = this.or(other)
+
+infix fun QueryColumn.`=`(value: Any?): QueryCondition = this.eq(value)
+
+infix fun QueryColumn.`in`(value: Collection): QueryCondition = this.`in`(value)
+
+fun QueryColumn.`in`(vararg values: Array): QueryCondition = this.`in`(values.asList())
+
+infix fun QueryWrapper.`as`(alias: String) = this.`as`(alias)
+
+infix fun Joiner.`as`(alias: String?): Joiner = this.`as`(alias)
+
+infix fun Joiner.on(on: String?): M = this.on(on)
+
+infix fun Joiner.on(on: QueryCondition?): M = this.on(on)
+
+infix fun Joiner.on(consumer: Consumer): M = this.on(consumer)
+
diff --git a/mybatis-flex-kotlin/src/main/java/com/mybatisflex/kotlin/scope/QueryScope.kt b/mybatis-flex-kotlin/src/main/java/com/mybatisflex/kotlin/scope/QueryScope.kt
new file mode 100755
index 00000000..70a88d3d
--- /dev/null
+++ b/mybatis-flex-kotlin/src/main/java/com/mybatisflex/kotlin/scope/QueryScope.kt
@@ -0,0 +1,45 @@
+package com.mybatisflex.kotlin.scope
+
+import com.mybatisflex.core.query.QueryColumn
+import com.mybatisflex.core.query.QueryCondition
+import com.mybatisflex.core.query.QueryWrapper
+import com.mybatisflex.core.table.TableDef
+/**
+ * 查询作用域
+ * @author 卡莫sama(yuanjiashuai)
+ * @date 2023/8/7
+ */
+class QueryScope :QueryWrapper() {
+ companion object CurrentQueryScope : ThreadLocal()
+
+ fun from(init: (QueryScope.() -> Unit)? = null): QueryWrapper = this.from(queryScope(init = init))
+
+ fun where(tableDef: T, build: T.() -> QueryCondition): QueryWrapper = this.where(build(tableDef))
+
+ fun where(build: QueryScope.() -> QueryCondition): QueryWrapper = this.where(build(this))
+
+ operator fun String.get(name: String): QueryColumn = QueryColumn(this, name)
+
+ operator fun String.unaryMinus(): QueryColumn = QueryColumn(this)
+
+}
+
+
+fun queryScope(vararg columns: QueryColumn?, init: (QueryScope.() -> Unit)? = null): QueryWrapper {
+ val builder = QueryScope()
+
+ if (columns.isNotEmpty()) {
+ builder.select(columns)
+ }
+ //用于嵌套查询拿到上层查询包装对象
+ init?.also {
+ val prentQueryScope = QueryScope.get()
+ QueryScope.set(builder)
+ it(builder)
+ QueryScope.set(prentQueryScope)
+ }
+
+ return builder
+}
+
+
diff --git a/mybatis-flex-kotlin/src/test/java/com/mybatisflex/kotlintest/ExtensionTest.kt b/mybatis-flex-kotlin/src/test/java/com/mybatisflex/kotlintest/ExtensionTest.kt
new file mode 100755
index 00000000..e54fb6be
--- /dev/null
+++ b/mybatis-flex-kotlin/src/test/java/com/mybatisflex/kotlintest/ExtensionTest.kt
@@ -0,0 +1,76 @@
+package com.myba
+
+import com.mybatisflex.kotlin.extend.entry.batchDeleteById
+
+import com.mybatisflex.core.BaseMapper
+import com.mybatisflex.core.MybatisFlexBootstrap
+import com.mybatisflex.core.audit.AuditManager
+import com.mybatisflex.core.audit.ConsoleMessageCollector
+import com.mybatisflex.kotlin.entry.Entry
+import com.mybatisflex.kotlin.extend.db.DB
+import com.mybatisflex.kotlin.extend.db.DB.filter
+import com.mybatisflex.kotlin.extend.entry.all
+import com.mybatisflex.kotlin.extend.entry.batchInsert
+import com.mybatisflex.kotlin.extend.entry.batchUpdate
+import com.mybatisflex.kotlin.extend.mapper.queryList
+import com.mybatisflex.kotlin.extend.sql.*
+import com.mybatisflex.kotlintest.entry.Account
+import com.mybatisflex.kotlintest.entry.table.AccountTableDef.ACCOUNT
+import org.springframework.jdbc.datasource.embedded.EmbeddedDatabaseBuilder
+import org.springframework.jdbc.datasource.embedded.EmbeddedDatabaseType
+import javax.sql.DataSource
+import kotlin.streams.toList
+
+
+fun main() {
+ val dataSource: DataSource = EmbeddedDatabaseBuilder()
+ .setType(EmbeddedDatabaseType.H2)
+ .addScript("schema.sql")
+ .addScript("data.sql")
+ .build()
+
+ AuditManager.setAuditEnable(true);
+ AuditManager.setMessageCollector(ConsoleMessageCollector())
+ MybatisFlexBootstrap.getInstance()
+ .addMapper(AccountMapper::class.java)
+ .setDataSource(dataSource)
+ .start()
+ filter {
+ ACCOUNT.AGE `=` 12 or
+ `if`(true) { ACCOUNT.ID `in` listOf(1, 2) }
+ }.stream().peek(::println).peek { it.id = it.id!!.plus(2) }.forEach(Entry::save)
+ println("保存后————————")
+ DB.mapper().findByAge(18,1,2).stream().peek { println(it) }.forEach(Entry::deleteById)
+ println("删除后————————")
+ ACCOUNT.all().stream().peek { println(it) }.map { it.userName = "sa"
+ it }.forEach(Entry::update)
+ println("更新后————————")
+ ACCOUNT.all().stream().peek { println(it) }.map {
+ it.id = it.id!!.plus(5)
+ it.userName = "423423"
+ it }.toList().batchInsert()
+ println("批量插入后————————")
+ ACCOUNT.all().stream().peek { println(it) }.toList().filter { it.id!!.rem(2) == 0 }.batchDeleteById()
+ println("批量删除后————————")
+ ACCOUNT.all().stream().peek { println(it) }.toList().filter { it.id!!.rem(3) == 0 }.map { it.userName = "哈哈"
+ it }.batchUpdate()
+ println("批量更新后————————")
+ ACCOUNT.all().stream().forEach { println(it) }
+}
+
+
+@JvmDefaultWithCompatibility
+interface AccountMapper : BaseMapper {
+
+ fun findByAge(age: Int, vararg ids: Int): List = queryList {
+ select(ACCOUNT.ALL_COLUMNS)
+ from(ACCOUNT)
+ where(ACCOUNT) {
+ (AGE `=` age) and `if`(true) {
+ ID `in` ids.asList()
+ }
+ }
+ }
+
+}
+
diff --git a/mybatis-flex-kotlin/src/test/java/com/mybatisflex/kotlintest/entry/Account.kt b/mybatis-flex-kotlin/src/test/java/com/mybatisflex/kotlintest/entry/Account.kt
new file mode 100755
index 00000000..22242832
--- /dev/null
+++ b/mybatis-flex-kotlin/src/test/java/com/mybatisflex/kotlintest/entry/Account.kt
@@ -0,0 +1,25 @@
+package com.mybatisflex.kotlintest.entry
+
+import com.mybatisflex.annotation.Column
+import com.mybatisflex.annotation.Id
+import com.mybatisflex.annotation.NoneListener
+import com.mybatisflex.annotation.Table
+import com.mybatisflex.kotlin.entry.Entry
+import java.util.*
+
+/**
+ * 测试用数据类(最好不要写成data class,否则需要与数据库字段数据顺序一致)
+ * @author 卡莫sama(yuanjiashuai)
+ * @date 2023/8/7
+ */
+@Table(value = "tb_account", onUpdate = [NoneListener::class])
+data class Account(
+ @Id var id: Int?,
+ @Column("u_name") var userName: String?,
+ var age: Int?,
+ var birthday: Date?,
+ ) : Entry(){
+ override fun toString(): String {
+ return "Account(id=$id, userName=$userName, birthday=$birthday, age=$age)"
+ }
+}
diff --git a/mybatis-flex-kotlin/src/test/resources/data.sql b/mybatis-flex-kotlin/src/test/resources/data.sql
new file mode 100755
index 00000000..228b8319
--- /dev/null
+++ b/mybatis-flex-kotlin/src/test/resources/data.sql
@@ -0,0 +1,4 @@
+INSERT INTO tb_account
+VALUES (1, 'Michael Yang', 18, '2020-01-11');
+INSERT INTO tb_account
+VALUES (2, 'Michael Zhanng', 20, '2020-01-11');
diff --git a/mybatis-flex-kotlin/src/test/resources/mybatis-flex.properties b/mybatis-flex-kotlin/src/test/resources/mybatis-flex.properties
new file mode 100755
index 00000000..b25cdd95
--- /dev/null
+++ b/mybatis-flex-kotlin/src/test/resources/mybatis-flex.properties
@@ -0,0 +1,4 @@
+processor.mappersGenerateEnable=false
+processor.tablesNameStyle=upCase
+processor.tablesDefSuffix=Def
+processor.allInTables=true
diff --git a/mybatis-flex-kotlin/src/test/resources/schema.sql b/mybatis-flex-kotlin/src/test/resources/schema.sql
new file mode 100755
index 00000000..40881a74
--- /dev/null
+++ b/mybatis-flex-kotlin/src/test/resources/schema.sql
@@ -0,0 +1,15 @@
+CREATE TABLE IF NOT EXISTS `tb_account`
+(
+ `id` INTEGER PRIMARY KEY,
+ `u_name` VARCHAR(100) NOT NULL,
+ `age` INTEGER,
+ `birthday` DATETIME
+);
+
+CREATE TABLE IF NOT EXISTS `tb_account1`
+(
+ `id` INTEGER PRIMARY KEY,
+ `u_name` VARCHAR(100) NOT NULL,
+ `age` INTEGER,
+ `birthday` DATETIME
+);
diff --git a/pom.xml b/pom.xml
index b456525c..8ba1dd98 100644
--- a/pom.xml
+++ b/pom.xml
@@ -48,6 +48,7 @@
mybatis-flex-solon-plugin
mybatis-flex-test
mybatis-flex-processor
+ mybatis-flex-kotlin