mirror of
https://github.com/tursom/TursomServer.git
synced 2025-03-27 20:40:29 +08:00
update
This commit is contained in:
parent
cc32906fc9
commit
887f04bb06
@ -7,5 +7,5 @@ import kotlin.reflect.KClass
|
||||
annotation class Key(
|
||||
val key: String = "",
|
||||
val clazz: KClass<*> = Any::class,
|
||||
val handler: String = ""
|
||||
val handler: String = "",
|
||||
)
|
||||
|
@ -5,5 +5,5 @@ import kotlin.reflect.KClass
|
||||
@Retention(AnnotationRetention.RUNTIME)
|
||||
@Target(AnnotationTarget.CLASS)
|
||||
annotation class NoPropertyClone(
|
||||
vararg val classList: KClass<*>
|
||||
vararg val classList: KClass<*>,
|
||||
)
|
@ -9,7 +9,7 @@ annotation class Relation(
|
||||
val property: String = "",
|
||||
val skip: Boolean = false,
|
||||
val handler: String = "",
|
||||
val handleClass: KClass<*> = Any::class
|
||||
val handleClass: KClass<*> = Any::class,
|
||||
)
|
||||
|
||||
|
||||
|
@ -3,5 +3,5 @@ package cn.tursom.core.clone
|
||||
@Retention(AnnotationRetention.RUNTIME)
|
||||
@Target(AnnotationTarget.FIELD)
|
||||
annotation class Relations(
|
||||
vararg val relations: Relation
|
||||
vararg val relations: Relation,
|
||||
)
|
@ -5,6 +5,9 @@ plugins {
|
||||
|
||||
dependencies {
|
||||
api(project(":"))
|
||||
implementation(project(":ts-core"))
|
||||
implementation(project(":ts-core:ts-clone"))
|
||||
implementation(project(":ts-core:ts-log"))
|
||||
api(group = "me.liuwj.ktorm", name = "ktorm-core", version = "3.1.0")
|
||||
compileOnly(group = "com.baomidou", name = "mybatis-plus", version = "3.4.2")
|
||||
compileOnly(group = "com.google.code.gson", name = "gson", version = "2.8.6")
|
||||
|
@ -1,6 +1,6 @@
|
||||
package cn.tursom.database
|
||||
|
||||
import com.ddbes.kotlin.Utils
|
||||
import cn.tursom.core.Utils
|
||||
import com.google.gson.Gson
|
||||
import me.liuwj.ktorm.schema.SqlType
|
||||
import java.lang.reflect.Type
|
||||
@ -12,7 +12,7 @@ import java.sql.Types
|
||||
class JsonType<T : Any>(
|
||||
val clazz: Type,
|
||||
type: Int = Types.VARCHAR,
|
||||
val gson: Gson = Utils.gson
|
||||
val gson: Gson = Utils.gson,
|
||||
) : SqlType<T>(type, "json") {
|
||||
constructor(clazz: Class<T>, type: Int = Types.VARCHAR) : this(clazz as Type, type)
|
||||
|
||||
|
@ -2,9 +2,8 @@
|
||||
|
||||
package cn.tursom.database
|
||||
|
||||
import com.ddbes.kotlin.Utils
|
||||
import com.ddbes.kotlin.jdbc.simpTableField
|
||||
import com.ddbes.kotlin.uncheckedCast
|
||||
import cn.tursom.core.Utils
|
||||
import cn.tursom.core.uncheckedCast
|
||||
import com.google.gson.Gson
|
||||
import me.liuwj.ktorm.dsl.Query
|
||||
import me.liuwj.ktorm.dsl.QueryRowSet
|
||||
|
247
ts-database/src/main/kotlin/cn/tursom/database/TableField.kt
Normal file
247
ts-database/src/main/kotlin/cn/tursom/database/TableField.kt
Normal file
@ -0,0 +1,247 @@
|
||||
/**
|
||||
* SQL 访问增强工具,实现从属性到数据库字段的自动映射
|
||||
* @author 王景阔
|
||||
* 例:
|
||||
* Files::name.tableField
|
||||
* 可获得 Files 的 name 属性对应的字段名。
|
||||
*/
|
||||
|
||||
@file:Suppress("unused")
|
||||
|
||||
package cn.tursom.database
|
||||
|
||||
import com.baomidou.mybatisplus.annotation.TableField
|
||||
import com.baomidou.mybatisplus.annotation.TableName
|
||||
import org.apache.ibatis.type.TypeHandler
|
||||
import java.lang.reflect.Field
|
||||
import java.lang.reflect.Modifier
|
||||
import kotlin.reflect.KClass
|
||||
import kotlin.reflect.KProperty
|
||||
import kotlin.reflect.KProperty1
|
||||
import kotlin.reflect.full.companionObjectInstance
|
||||
import kotlin.reflect.full.findAnnotation
|
||||
import kotlin.reflect.jvm.javaField
|
||||
import kotlin.reflect.jvm.javaGetter
|
||||
|
||||
/**
|
||||
* 数据库访问增强接口
|
||||
* @author 王景阔
|
||||
* 设计上使用代理模式实现字段名缓存
|
||||
*/
|
||||
interface TableField<T> {
|
||||
var tableName: String
|
||||
val fieldMap: Map<KProperty1<out T, *>, String>
|
||||
val simpFieldMap: Map<KProperty1<out T, *>, String>
|
||||
val fullFieldMap: Map<KProperty1<out T, *>, String>
|
||||
val properties: Array<out KProperty1<out T, *>>
|
||||
val allField: Array<out String>
|
||||
val fullNameField: Array<out String>
|
||||
val typeHandlerMap: Map<KProperty1<out T, *>, TypeHandler<Any>>
|
||||
|
||||
//operator fun get(field: KProperty<*>): String = fieldMap[field] ?: field.tableField
|
||||
operator fun get(field: KProperty1<out T, *>): String = fieldMap[field] ?: field.simpTableField
|
||||
}
|
||||
|
||||
|
||||
val <T> Iterable<KProperty1<out T, *>>.filterNotExists
|
||||
get() = filter {
|
||||
it.javaField != null &&
|
||||
it.findAnnotation() ?: it.javaField?.getAnnotation(Transient::class.java) == null &&
|
||||
!Modifier.isTransient(it.javaField?.modifiers ?: Modifier.TRANSIENT) &&
|
||||
it.javaField?.getAnnotation(com.baomidou.mybatisplus.annotation.TableField::class.java)?.exist != false
|
||||
}
|
||||
|
||||
@get:JvmName("filterNotExistsPair")
|
||||
val <T> Iterable<Pair<KProperty1<T, *>, *>>.filterNotExists
|
||||
get() = filter { (it, _) ->
|
||||
it.javaField != null &&
|
||||
it.findAnnotation() ?: it.javaField?.getAnnotation(Transient::class.java) == null &&
|
||||
!Modifier.isTransient(it.javaField?.modifiers ?: Modifier.TRANSIENT) &&
|
||||
it.javaField?.getAnnotation(com.baomidou.mybatisplus.annotation.TableField::class.java)?.exist != false
|
||||
}
|
||||
|
||||
@get:JvmName("filterNotExistsKProperty")
|
||||
val Iterable<KProperty<*>>.filterNotExists
|
||||
get() = filter {
|
||||
it.javaField != null &&
|
||||
it.findAnnotation() ?: it.javaField?.getAnnotation(Transient::class.java) == null &&
|
||||
!Modifier.isTransient(it.javaField?.modifiers ?: Modifier.TRANSIENT) &&
|
||||
it.javaField?.getAnnotation(com.baomidou.mybatisplus.annotation.TableField::class.java)?.exist != false
|
||||
}
|
||||
|
||||
@get:JvmName("filterNotExistsKPropertyPair")
|
||||
val Iterable<Pair<KProperty<*>, *>>.filterNotExists
|
||||
get() = filter { (it, _) ->
|
||||
it.javaField != null &&
|
||||
it.findAnnotation() ?: it.javaField?.getAnnotation(Transient::class.java) == null &&
|
||||
!Modifier.isTransient(it.javaField?.modifiers ?: Modifier.TRANSIENT) &&
|
||||
it.javaField?.getAnnotation(com.baomidou.mybatisplus.annotation.TableField::class.java)?.exist != false
|
||||
}
|
||||
|
||||
val String.sqlName: String
|
||||
get() {
|
||||
val sb = StringBuilder()
|
||||
val iterator = iterator()
|
||||
sb.append(iterator.nextChar().toLowerCase())
|
||||
iterator.forEach {
|
||||
if (it.isUpperCase()) {
|
||||
sb.append('_')
|
||||
sb.append(it.toLowerCase())
|
||||
} else {
|
||||
sb.append(it)
|
||||
}
|
||||
}
|
||||
return sb.toString()
|
||||
}
|
||||
|
||||
val KClass<*>.tableName: String get() = findAnnotation<TableName>()?.value ?: simpleName!!.sqlName
|
||||
val Class<*>.tableName: String get() = getAnnotation(TableName::class.java)?.value ?: simpleName.sqlName
|
||||
val KProperty<*>.tableFieldName: String? get() = javaField?.getAnnotation(TableField::class.java)?.value
|
||||
val KProperty<*>.simpTableField: String get() = tableFieldName ?: name.sqlName
|
||||
val KProperty<*>.selectionTableField: String
|
||||
get() = tableFieldName?.let { if (it.isNotEmpty()) "$it as ${name.sqlName}" else null } ?: name.sqlName
|
||||
|
||||
inline val <reified T> KProperty1<out T, *>.tableField: String
|
||||
get() {
|
||||
val companion = T::class.companionObjectInstance
|
||||
return if (companion is cn.tursom.database.TableField<*>) {
|
||||
@Suppress("UNCHECKED_CAST")
|
||||
companion as cn.tursom.database.TableField<T>
|
||||
companion[this]
|
||||
} else {
|
||||
selectionTableField
|
||||
}
|
||||
}
|
||||
|
||||
inline val <reified T : Any> KProperty1<out T, *>.fullTableField: String
|
||||
get() {
|
||||
val companion = T::class.companionObjectInstance
|
||||
return if (companion is cn.tursom.database.TableField<*>) {
|
||||
@Suppress("UNCHECKED_CAST")
|
||||
companion as cn.tursom.database.TableField<T>
|
||||
companion.fullFieldMap[this] ?: "${companion.tableName}.${companion[this]}"
|
||||
} else {
|
||||
"${T::class.tableName}.$selectionTableField"
|
||||
}
|
||||
}
|
||||
|
||||
val KProperty<*>.fullTableField: String
|
||||
get() {
|
||||
val kotlin = (javaGetter?.declaringClass ?: javaField?.declaringClass)?.kotlin!!
|
||||
return "${kotlin.tableName}.$selectionTableField"
|
||||
}
|
||||
|
||||
val Field.tableField: String
|
||||
get() {
|
||||
val tableField = getAnnotation(TableField::class.java)
|
||||
return tableField?.value?.let { if (it.isNotEmpty()) "$it as ${name.sqlName}" else null } ?: name.sqlName
|
||||
}
|
||||
|
||||
val KProperty<*>.directTableField: String
|
||||
get() = simpTableField
|
||||
|
||||
inline val <reified T> KProperty1<out T, *>.directTableField: String
|
||||
get() {
|
||||
val companion = T::class.companionObjectInstance
|
||||
return if (companion is cn.tursom.database.TableField<*>) {
|
||||
@Suppress("UNCHECKED_CAST")
|
||||
companion as cn.tursom.database.TableField<T>
|
||||
companion.simpFieldMap[this] ?: simpTableField
|
||||
} else {
|
||||
simpTableField
|
||||
}
|
||||
}
|
||||
|
||||
inline val <reified T> Array<out KProperty1<out T, *>>.directTableField: Array<out String> get() = asList().directTableField
|
||||
inline val <reified T> Collection<KProperty1<out T, *>>.directTableField: Array<out String>
|
||||
get() {
|
||||
val companion = T::class.companionObjectInstance
|
||||
val fieldList = arrayOfNulls<String>(size)
|
||||
filterNotExists.forEach {
|
||||
if (companion is cn.tursom.database.TableField<*>) {
|
||||
@Suppress("UNCHECKED_CAST")
|
||||
companion as cn.tursom.database.TableField<T>
|
||||
companion.simpFieldMap[it] ?: it.simpTableField
|
||||
} else {
|
||||
it.simpTableField
|
||||
}
|
||||
}
|
||||
@Suppress("UNCHECKED_CAST")
|
||||
return fieldList as Array<out String>
|
||||
}
|
||||
|
||||
val Field.directTableField: String
|
||||
get() {
|
||||
val tableField = getAnnotation(TableField::class.java)
|
||||
return tableField?.value?.ifEmpty { null } ?: name.sqlName
|
||||
}
|
||||
|
||||
inline val <reified T> Array<out KProperty1<T, *>>.tableField: Array<out String> get() = asList().tableField
|
||||
inline val <reified T> Collection<KProperty1<T, *>>.tableField: Array<out String>
|
||||
get() {
|
||||
val companion = T::class.companionObjectInstance
|
||||
return if (companion is cn.tursom.database.TableField<*>) {
|
||||
@Suppress("UNCHECKED_CAST")
|
||||
companion as cn.tursom.database.TableField<T>
|
||||
filterNotExists.map { companion[it] }
|
||||
} else {
|
||||
filterNotExists.map { it.simpTableField }
|
||||
}.toTypedArray()
|
||||
}
|
||||
|
||||
inline val <reified T> Map<out KProperty1<T, *>, *>.tableField: Map<String, *>
|
||||
get() {
|
||||
val companion = T::class.companionObjectInstance
|
||||
return if (companion is cn.tursom.database.TableField<*>) {
|
||||
@Suppress("UNCHECKED_CAST")
|
||||
companion as cn.tursom.database.TableField<T>
|
||||
mapKeys { companion.simpFieldMap[it.key] ?: it.key.directTableField }
|
||||
} else {
|
||||
mapKeys { it.key.directTableField }
|
||||
}
|
||||
}
|
||||
|
||||
inline val <reified T> Array<out Pair<KProperty1<T, *>, *>>.tableField: Map<String, *> get() = asList().tableField
|
||||
inline val <reified T> Collection<Pair<KProperty1<T, *>, *>>.tableField: Map<String, *>
|
||||
get() {
|
||||
val companion = T::class.companionObjectInstance
|
||||
return if (companion is cn.tursom.database.TableField<*>) {
|
||||
@Suppress("UNCHECKED_CAST")
|
||||
companion as cn.tursom.database.TableField<T>
|
||||
filterNotExists.associate { (companion.simpFieldMap[it.first] ?: it.first.directTableField) to it.second }
|
||||
} else {
|
||||
filterNotExists.associate { it.first.directTableField to it.second }
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
val Array<out Pair<KProperty<*>, *>>.fullTableField: Map<String, *> get() = asList().fullTableField
|
||||
val Collection<Pair<KProperty<*>, *>>.fullTableField: Map<String, *>
|
||||
get() {
|
||||
val map = HashMap<String, Any?>(size)
|
||||
filterNotExists.forEach { (property, value) ->
|
||||
map[property.fullTableField] = value
|
||||
}
|
||||
return map
|
||||
}
|
||||
|
||||
val Array<out KProperty<*>>.fullTableField: Array<out String> get() = asList().fullTableField
|
||||
|
||||
@get:JvmName("getKPropertyFullTableField")
|
||||
val Collection<KProperty<*>>.fullTableField: Array<out String>
|
||||
get() = filterNotExists.map { it.fullTableField }.toTypedArray()
|
||||
|
||||
|
||||
inline val <reified T> Array<out KProperty1<T, *>>.fullTableField: Array<out String> get() = asList().fullTableField
|
||||
inline val <reified T> Collection<KProperty1<T, *>>.fullTableField: Array<out String>
|
||||
get() {
|
||||
val tableName = T::class.tableName
|
||||
val companion = T::class.companionObjectInstance
|
||||
return if (companion is cn.tursom.database.TableField<*>) {
|
||||
@Suppress("UNCHECKED_CAST")
|
||||
companion as cn.tursom.database.TableField<T>
|
||||
filterNotExists.map { "$tableName.${companion[it]}" }
|
||||
} else {
|
||||
filterNotExists.map { "$tableName.${it.simpTableField}" }
|
||||
}.toTypedArray()
|
||||
}
|
@ -0,0 +1,69 @@
|
||||
package cn.tursom.database
|
||||
|
||||
import cn.tursom.core.uncheckedCast
|
||||
import cn.tursom.log.impl.Slf4jImpl
|
||||
import org.apache.ibatis.type.TypeHandler
|
||||
import java.lang.reflect.Modifier
|
||||
import kotlin.reflect.KClass
|
||||
import kotlin.reflect.KProperty1
|
||||
import kotlin.reflect.full.findAnnotation
|
||||
import kotlin.reflect.full.memberProperties
|
||||
import kotlin.reflect.jvm.javaField
|
||||
import kotlin.reflect.jvm.jvmName
|
||||
|
||||
/**
|
||||
* 自动注入表单名称映射
|
||||
* @author 王景阔
|
||||
* 实现使用 类名[属性对象] 的方式来获取数据库属性名
|
||||
* 同时为 KProperty<*>.tableField 实现缓存加速
|
||||
*/
|
||||
open class TableFieldImpl<T>(clazz: KClass<*>? = null) : TableField<T> {
|
||||
companion object : Slf4jImpl()
|
||||
|
||||
final override var tableName: String
|
||||
|
||||
@Transient
|
||||
final override val fieldMap = HashMap<KProperty1<out T, *>, String>()
|
||||
final override val simpFieldMap = HashMap<KProperty1<out T, *>, String>()
|
||||
final override val fullFieldMap = HashMap<KProperty1<out T, *>, String>()
|
||||
|
||||
@Transient
|
||||
final override val allField: Array<out String>
|
||||
final override val fullNameField: Array<out String>
|
||||
final override val properties: Array<KProperty1<T, *>>
|
||||
override val typeHandlerMap = HashMap<KProperty1<out T, *>, TypeHandler<Any>>()
|
||||
|
||||
init {
|
||||
if (clazz == null && this.javaClass == TableFieldImpl::class.java) {
|
||||
throw NotImplementedError("需提供解析类")
|
||||
}
|
||||
@Suppress("UNCHECKED_CAST")
|
||||
(clazz ?: this.javaClass.kotlin.run {
|
||||
if (isCompanion) {
|
||||
java.classLoader.loadClass(jvmName.dropLast(10)).kotlin
|
||||
} else {
|
||||
this
|
||||
}
|
||||
}).also {
|
||||
tableName = it.tableName
|
||||
}.memberProperties
|
||||
.uncheckedCast<Collection<KProperty1<out T, *>>>()
|
||||
.filter {
|
||||
it.javaField != null &&
|
||||
it.findAnnotation() ?: it.javaField?.getAnnotation(Transient::class.java) == null &&
|
||||
!Modifier.isTransient(it.javaField?.modifiers ?: Modifier.TRANSIENT) &&
|
||||
it.javaField?.getAnnotation(com.baomidou.mybatisplus.annotation.TableField::class.java)?.exist != false
|
||||
}
|
||||
.forEach {
|
||||
val simpTableField = it.simpTableField
|
||||
trace("mapping {}::{}", tableName, simpTableField)
|
||||
simpFieldMap[it] = simpTableField
|
||||
fieldMap[it] = it.selectionTableField
|
||||
fullFieldMap[it] = "$tableName.${it.name.sqlName}"
|
||||
it.findAnnotation<com.baomidou.mybatisplus.annotation.TableField>()?.typeHandler
|
||||
}
|
||||
properties = fieldMap.keys.toTypedArray().uncheckedCast()
|
||||
allField = fieldMap.values.toTypedArray()
|
||||
fullNameField = allField.map { "$tableName.$it" }.toTypedArray()
|
||||
}
|
||||
}
|
@ -20,6 +20,6 @@ interface TypeAdapter<T : Any> {
|
||||
*/
|
||||
fun register(
|
||||
table: BaseTable<Any>,
|
||||
field: KProperty1<Any, T>
|
||||
field: KProperty1<Any, T>,
|
||||
): Column<T>?
|
||||
}
|
@ -1,8 +1,8 @@
|
||||
package cn.tursom.database
|
||||
|
||||
import com.ddbes.kotlin.classutil.getClassByPackage
|
||||
import com.ddbes.kotlin.clone.InstantAllocator
|
||||
import com.ddbes.kotlin.uncheckedCast
|
||||
import cn.tursom.core.clone.InstantAllocator
|
||||
import cn.tursom.core.getClassByPackage
|
||||
import cn.tursom.core.uncheckedCast
|
||||
import me.liuwj.ktorm.schema.BaseTable
|
||||
import me.liuwj.ktorm.schema.Column
|
||||
import java.util.concurrent.ConcurrentSkipListMap
|
||||
|
332
ts-database/src/main/kotlin/cn/tursom/database/WrapperEnhance.kt
Normal file
332
ts-database/src/main/kotlin/cn/tursom/database/WrapperEnhance.kt
Normal file
@ -0,0 +1,332 @@
|
||||
/**
|
||||
* QueryWrapper kotlin 化改造
|
||||
* @author 王景阔
|
||||
*/
|
||||
@file:Suppress("unused")
|
||||
|
||||
package cn.tursom.database
|
||||
|
||||
import cn.tursom.core.uncheckedCast
|
||||
import cn.tursom.database.annotations.Getter
|
||||
import cn.tursom.log.impl.Slf4jImpl
|
||||
import com.baomidou.mybatisplus.annotation.TableField
|
||||
import com.baomidou.mybatisplus.core.conditions.AbstractWrapper
|
||||
import com.baomidou.mybatisplus.core.conditions.ISqlSegment
|
||||
import com.baomidou.mybatisplus.core.conditions.Wrapper
|
||||
import com.baomidou.mybatisplus.core.conditions.interfaces.Compare
|
||||
import com.baomidou.mybatisplus.core.conditions.interfaces.Func
|
||||
import com.baomidou.mybatisplus.core.conditions.interfaces.Join
|
||||
import com.baomidou.mybatisplus.core.conditions.query.Query
|
||||
import com.baomidou.mybatisplus.core.conditions.update.Update
|
||||
import com.baomidou.mybatisplus.core.toolkit.Constants
|
||||
import java.lang.reflect.Field
|
||||
import java.lang.reflect.Modifier
|
||||
import java.util.*
|
||||
import java.util.concurrent.atomic.AtomicInteger
|
||||
import kotlin.reflect.KProperty
|
||||
import kotlin.reflect.KProperty1
|
||||
import kotlin.reflect.full.findAnnotation
|
||||
import kotlin.reflect.full.memberProperties
|
||||
import kotlin.reflect.jvm.isAccessible
|
||||
import kotlin.reflect.jvm.javaField
|
||||
import kotlin.reflect.jvm.javaGetter
|
||||
|
||||
val logger = Slf4jImpl.getLogger("com.ddbes.pan.kit.jdbc")
|
||||
|
||||
val select: Query<*, *, Any>.(Array<out Any>) -> Any = Query<*, *, Any>::select
|
||||
|
||||
@Suppress("UNCHECKED_CAST")
|
||||
fun <T, Children : Wrapper<T>, Q> Query<Children, T, Q>.select(
|
||||
columns: Array<out Q>,
|
||||
): Children = (select as Query<Children, T, Q>.(Array<out Q>) -> Children)(columns)
|
||||
|
||||
/**
|
||||
* QueryWrapper<T>().select(T::fieldName, value)
|
||||
*/
|
||||
inline fun <reified T, Children : Wrapper<T>> Query<Children, T, String>.select(
|
||||
vararg columns: KProperty1<T, *>,
|
||||
): Children = select(columns.tableField)
|
||||
|
||||
fun <T, Children : Wrapper<T>> Query<Children, T, String>.select(
|
||||
vararg columns: KProperty<*>,
|
||||
): Children = fullSelect(*columns)
|
||||
|
||||
fun <T, Children : Wrapper<T>> Query<Children, T, String>.fullSelect(
|
||||
vararg columns: KProperty<*>,
|
||||
): Children = select(columns.fullTableField)
|
||||
|
||||
/**
|
||||
* QueryWrapper<T>().eq(T::fieldName, value)
|
||||
*/
|
||||
inline fun <reified T, Children : Wrapper<T>> Compare<Children, String>.eq(
|
||||
column: KProperty1<T, *>,
|
||||
value: Any,
|
||||
): Children = eq(column.directTableField, value)
|
||||
|
||||
fun <T, Children : Wrapper<T>> Compare<Children, String>.eq(
|
||||
column: KProperty<*>,
|
||||
value: Any,
|
||||
): Children = eq(column.directTableField, value)
|
||||
|
||||
inline fun <reified T, Children : Wrapper<T>> Compare<Children, String>.eq(
|
||||
column: Pair<KProperty1<T, *>, Any?>,
|
||||
): Children = eq(column.first.directTableField, column.second)
|
||||
|
||||
inline fun <reified T, Children : Wrapper<T>> Compare<Children, String>.eq(
|
||||
vararg pair: Pair<KProperty1<T, *>, Any?>,
|
||||
): Children = allEq(pair.tableField)
|
||||
|
||||
inline fun <reified T, Children : Wrapper<T>> Compare<Children, String>.eq(
|
||||
pair: Collection<Pair<KProperty1<T, *>, Any>>,
|
||||
): Children = allEq(pair.tableField)
|
||||
|
||||
fun <Children> Compare<Children, String>.eq(vararg pair: Pair<KProperty<*>, *>): Children = allEq(pair.fullTableField)
|
||||
|
||||
inline fun <reified T : Any, Children : Wrapper<T>> Compare<Children, String>.eq(entity: T): Children {
|
||||
val eqs = LinkedList<Pair<KProperty1<T, *>, Any>>()
|
||||
entity::class.memberProperties.uncheckedCast<Collection<KProperty1<T, *>>>().forEach {
|
||||
it.isAccessible = true
|
||||
eqs.add(it to (it(entity) ?: return@forEach))
|
||||
}
|
||||
return eq(eqs)
|
||||
}
|
||||
|
||||
/**
|
||||
* QueryWrapper<T>().allEq(mapOf(
|
||||
* T::fieldName1 to value1,
|
||||
* T::fieldName2 to value2,
|
||||
* ...
|
||||
* ))
|
||||
*/
|
||||
inline fun <reified T, Children : Wrapper<T>> Compare<Children, String>.allEq(map: Map<out KProperty1<T, *>, *>): Children =
|
||||
allEq(map.tableField)
|
||||
|
||||
inline fun <reified T, Children : Wrapper<T>> Compare<Children, String>.allEq(vararg pair: Pair<KProperty1<T, *>, *>): Children =
|
||||
allEq(pair.tableField)
|
||||
|
||||
fun <Children> Compare<Children, String>.allEq(vararg pair: Pair<KProperty<*>, *>): Children =
|
||||
allEq(pair.fullTableField)
|
||||
|
||||
fun <Children> Compare<Children, String>.allFullEq(vararg pair: Pair<KProperty<*>, *>): Children =
|
||||
allEq(pair.fullTableField)
|
||||
|
||||
inline fun <reified T, Children : Wrapper<T>> Compare<Children, String>.ne(
|
||||
column: KProperty1<T, *>,
|
||||
value: Any?,
|
||||
): Children = ne(column.directTableField, value)
|
||||
|
||||
inline fun <reified T, Children : Wrapper<T>> Compare<Children, String>.gt(
|
||||
column: KProperty1<T, *>,
|
||||
value: Any?,
|
||||
): Children = gt(column.directTableField, value)
|
||||
|
||||
inline fun <reified T, Children : Wrapper<T>> Compare<Children, String>.ge(
|
||||
column: KProperty1<T, *>,
|
||||
value: Any?,
|
||||
): Children = ge(column.directTableField, value)
|
||||
|
||||
inline fun <reified T, Children : Wrapper<T>> Compare<Children, String>.lt(
|
||||
column: KProperty1<T, *>,
|
||||
value: Any?,
|
||||
): Children = lt(column.directTableField, value)
|
||||
|
||||
inline fun <reified T, Children : Wrapper<T>> Compare<Children, String>.le(
|
||||
column: KProperty1<T, *>,
|
||||
value: Any?,
|
||||
): Children = le(column.directTableField, value)
|
||||
|
||||
inline fun <reified T, Children : Wrapper<T>> Compare<Children, String>.between(
|
||||
column: KProperty1<T, *>,
|
||||
val1: Any?,
|
||||
val2: Any?,
|
||||
): Children = between(column.directTableField, val1, val2)
|
||||
|
||||
inline fun <reified T, Children : Wrapper<T>> Compare<Children, String>.notBetween(
|
||||
column: KProperty1<T, *>,
|
||||
val1: Any?,
|
||||
val2: Any?,
|
||||
): Children = notBetween(column.directTableField, val1, val2)
|
||||
|
||||
inline fun <reified T, Children : Wrapper<T>> Compare<Children, String>.like(
|
||||
column: KProperty1<T, *>,
|
||||
value: Any?,
|
||||
): Children = like(column.directTableField, value)
|
||||
|
||||
inline fun <reified T, Children : Wrapper<T>> Compare<Children, String>.notLike(
|
||||
column: KProperty1<T, *>,
|
||||
value: Any?,
|
||||
): Children = notLike(column.directTableField, value)
|
||||
|
||||
inline fun <reified T, Children : Wrapper<T>> Compare<Children, String>.likeLeft(
|
||||
column: KProperty1<T, *>,
|
||||
value: Any?,
|
||||
): Children = likeLeft(column.directTableField, value)
|
||||
|
||||
inline fun <reified T, Children : Wrapper<T>> Compare<Children, String>.likeRight(
|
||||
column: KProperty1<T, *>,
|
||||
value: Any?,
|
||||
): Children = likeRight(column.directTableField, value)
|
||||
|
||||
inline fun <reified T, Children : Wrapper<T>> Func<Children, String>.having(
|
||||
column: KProperty1<T, *>,
|
||||
vararg value: Any?,
|
||||
): Children = having(column.directTableField, value)
|
||||
|
||||
inline fun <reified T, Children : Wrapper<T>> Func<Children, String>.isNull(column: KProperty1<T, *>): Children =
|
||||
isNull(column.directTableField)
|
||||
|
||||
inline fun <reified T, Children : Wrapper<T>> Func<Children, String>.isNotNull(column: KProperty1<T, *>): Children =
|
||||
isNotNull(column.directTableField)
|
||||
|
||||
inline fun <reified T, Children : Wrapper<T>> Func<Children, String>.`in`(
|
||||
column: KProperty1<T, *>,
|
||||
value: Any?,
|
||||
): Children = `in`(column.directTableField, value)
|
||||
|
||||
inline fun <reified T, Children : Wrapper<T>> Func<Children, String>.`in`(
|
||||
column: KProperty1<T, *>,
|
||||
value: Collection<Any?>,
|
||||
): Children = `in`(column.directTableField, value)
|
||||
|
||||
inline fun <reified T, Children : Wrapper<T>> Func<Children, String>.`in`(
|
||||
column: KProperty1<T, *>,
|
||||
vararg value: Any,
|
||||
): Children = `in`(column.directTableField, value)
|
||||
|
||||
inline fun <reified T, Children : Wrapper<T>> Func<Children, String>.notIn(
|
||||
column: KProperty1<T, *>,
|
||||
value: Collection<Any?>,
|
||||
): Children = notIn(column.directTableField, value)
|
||||
|
||||
inline fun <reified T, Children : Wrapper<T>> Func<Children, String>.notIn(
|
||||
column: KProperty1<T, *>,
|
||||
vararg value: Any,
|
||||
): Children = notIn(column.directTableField, value)
|
||||
|
||||
inline fun <reified T, Children : Wrapper<T>> Func<Children, String>.inSql(
|
||||
column: KProperty1<T, *>,
|
||||
value: String?,
|
||||
): Children = inSql(column.directTableField, value)
|
||||
|
||||
inline fun <reified T, Children : Wrapper<T>> Func<Children, String>.notInSql(
|
||||
column: KProperty1<T, *>,
|
||||
value: String?,
|
||||
): Children = notInSql(column.directTableField, value)
|
||||
|
||||
|
||||
val groupBy: Func<*, String>.(Array<out String>) -> Any = Func<*, String>::groupBy
|
||||
inline fun <reified T, Children : Wrapper<T>> Func<Children, String>.groupBy(column: KProperty1<T, *>): Children =
|
||||
groupBy(column.directTableField)
|
||||
|
||||
@Suppress("UNCHECKED_CAST")
|
||||
inline fun <reified T, Children : Wrapper<T>> Func<Children, String>.groupBy(vararg column: KProperty1<T, *>): Children =
|
||||
groupBy(column.directTableField) as Children
|
||||
|
||||
val orderByAsc: Func<*, String>.(Array<out String>) -> Any = Func<*, String>::orderByAsc
|
||||
inline fun <reified T, Children : Wrapper<T>> Func<Children, String>.orderByAsc(column: KProperty1<T, *>): Children =
|
||||
orderByAsc(column.directTableField)
|
||||
|
||||
@Suppress("UNCHECKED_CAST")
|
||||
inline fun <reified T, Children : Wrapper<T>> Func<Children, String>.orderByAsc(vararg column: KProperty1<T, *>): Children =
|
||||
orderByAsc(column.directTableField) as Children
|
||||
|
||||
val orderByDesc: Func<*, String>.(Array<out String>) -> Any = Func<*, String>::orderByDesc
|
||||
inline fun <reified T, Children : Wrapper<T>> Func<Children, String>.orderByDesc(column: KProperty1<T, *>): Children =
|
||||
orderByDesc(column.directTableField)
|
||||
|
||||
@Suppress("UNCHECKED_CAST")
|
||||
inline fun <reified T, Children : Wrapper<T>> Func<Children, String>.orderByDesc(vararg column: KProperty1<T, *>): Children =
|
||||
orderByDesc(column.directTableField) as Children
|
||||
|
||||
|
||||
/**
|
||||
* QueryWrapper<T>()
|
||||
* .xx()
|
||||
* .xxx()
|
||||
* ...
|
||||
* .limit1()
|
||||
*/
|
||||
fun <Children> Join<Children>.limit1(): Children = last("LIMIT 1")
|
||||
|
||||
inline fun <reified T, Children : Wrapper<T>> Update<Children, String>.set(
|
||||
column: KProperty1<T, *>,
|
||||
value: Any?,
|
||||
): Children {
|
||||
if (column.javaField == null || Modifier.isTransient(column.javaField?.modifiers ?: Modifier.TRANSIENT) ||
|
||||
column.javaField?.getAnnotation(TableField::class.java)?.exist == false
|
||||
) {
|
||||
return uncheckedCast()
|
||||
}
|
||||
val getter = column.findAnnotation<Getter>()
|
||||
val v = if (getter == null || !(value != null && getter.getterType.isInstance(value))) {
|
||||
value
|
||||
} else {
|
||||
val getterMethod = column.javaGetter!!.declaringClass.getDeclaredMethod(getter.getter, getter.getterType.java)
|
||||
getterMethod.isAccessible = true
|
||||
getterMethod.invoke(null, value)
|
||||
}
|
||||
return set(column.directTableField, v)
|
||||
}
|
||||
|
||||
inline fun <reified T, Children : Wrapper<T>> Update<Children, String>.set(vararg values: Pair<KProperty1<T, *>, Any?>): Children {
|
||||
var children: Children? = null
|
||||
values.forEach { (column, value) ->
|
||||
set(column, value).let {
|
||||
if (children == null) children = it
|
||||
}
|
||||
}
|
||||
return children ?: uncheckedCast()
|
||||
}
|
||||
|
||||
inline fun <reified T : Any, Children : Wrapper<T>> Update<Children, String>.set(value: T): Children {
|
||||
var children: Children? = null
|
||||
value::class.memberProperties
|
||||
.uncheckedCast<Collection<KProperty1<T, *>>>()
|
||||
.filter {
|
||||
it.javaField != null &&
|
||||
it.findAnnotation() ?: it.javaField?.getAnnotation(Transient::class.java) == null &&
|
||||
!Modifier.isTransient(it.javaField?.modifiers ?: Modifier.TRANSIENT) &&
|
||||
it.javaField?.getAnnotation(TableField::class.java)?.exist != false
|
||||
}
|
||||
.forEach { property ->
|
||||
property.isAccessible = true
|
||||
set(property, property.get(value) ?: return@forEach).let {
|
||||
if (children == null) children = it
|
||||
}
|
||||
}
|
||||
return children ?: uncheckedCast()
|
||||
}
|
||||
|
||||
object Regexp : ISqlSegment {
|
||||
override fun getSqlSegment(): String = "REGEXP"
|
||||
}
|
||||
|
||||
object WrapperEnhance : AbstractWrapper<Any, String, WrapperEnhance>() {
|
||||
override fun instance(): WrapperEnhance = this
|
||||
private val paramNameSeqField: Field =
|
||||
AbstractWrapper::class.java.getDeclaredField("paramNameSeq").apply { isAccessible = true }
|
||||
|
||||
init {
|
||||
initNeed()
|
||||
}
|
||||
|
||||
fun <T, W : AbstractWrapper<T, String, W>> regex(wrapper: W, column: String, value: Any): W {
|
||||
wrapper.expression.add(ISqlSegment { columnToString(column) }, Regexp, ISqlSegment {
|
||||
val genParamName = Constants.WRAPPER_PARAM + (paramNameSeqField.get(wrapper) as AtomicInteger).incrementAndGet()
|
||||
wrapper.paramNameValuePairs[genParamName] = value
|
||||
String.format(Constants.WRAPPER_PARAM_FORMAT, Constants.WRAPPER, genParamName)
|
||||
})
|
||||
return wrapper
|
||||
}
|
||||
}
|
||||
|
||||
fun <T, W : AbstractWrapper<T, String, W>> W.regex(column: String, value: Any): W =
|
||||
WrapperEnhance.regex(this, column, value)
|
||||
|
||||
inline fun <reified T, W : AbstractWrapper<T, String, W>> W.regex(
|
||||
column: KProperty1<T, *>, value: Any,
|
||||
): W = WrapperEnhance.regex(this, column.directTableField, value)
|
||||
|
||||
inline fun <reified T, W : AbstractWrapper<T, String, W>> W.regex(
|
||||
column: KProperty1<T, *>, regex: Regex,
|
||||
): W = WrapperEnhance.regex(this, column.directTableField, regex.toString())
|
@ -0,0 +1,10 @@
|
||||
package cn.tursom.database.annotations
|
||||
|
||||
import kotlin.reflect.KClass
|
||||
|
||||
/**
|
||||
* 很抱歉我暂时做不到兼容 mybatis 的 TypeHandler,只能用这种方式凑合一下了
|
||||
*/
|
||||
@Retention(AnnotationRetention.RUNTIME)
|
||||
@Target(AnnotationTarget.PROPERTY)
|
||||
annotation class Getter(val getter: String, val getterType: KClass<*>)
|
@ -1,6 +1,5 @@
|
||||
package cn.tursom.database.annotations
|
||||
|
||||
|
||||
@MustBeDocumented
|
||||
@Retention(AnnotationRetention.RUNTIME)
|
||||
@Target(AnnotationTarget.PROPERTY)
|
||||
|
@ -1,8 +1,8 @@
|
||||
package cn.tursom.database.typeadapter
|
||||
|
||||
import cn.tursom.core.uncheckedCast
|
||||
import cn.tursom.database.TypeAdapter
|
||||
import com.ddbes.kotlin.jdbc.simpTableField
|
||||
import com.ddbes.kotlin.uncheckedCast
|
||||
import cn.tursom.database.simpTableField
|
||||
import me.liuwj.ktorm.schema.BaseTable
|
||||
import me.liuwj.ktorm.schema.Column
|
||||
import me.liuwj.ktorm.schema.EnumSqlType
|
||||
|
Loading…
Reference in New Issue
Block a user