This commit is contained in:
tursom 2021-04-12 13:05:59 +08:00
parent cc32906fc9
commit 887f04bb06
48 changed files with 1055 additions and 396 deletions

View File

@ -5,7 +5,7 @@ import kotlin.reflect.KClass
@Retention(AnnotationRetention.RUNTIME)
@Target(AnnotationTarget.FIELD)
annotation class Key(
val key: String = "",
val clazz: KClass<*> = Any::class,
val handler: String = ""
val key: String = "",
val clazz: KClass<*> = Any::class,
val handler: String = "",
)

View File

@ -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<*>,
)

View File

@ -5,11 +5,11 @@ import kotlin.reflect.KClass
@Retention(AnnotationRetention.RUNTIME)
@Target(AnnotationTarget.FIELD)
annotation class Relation(
val clazz: KClass<*>,
val property: String = "",
val skip: Boolean = false,
val handler: String = "",
val handleClass: KClass<*> = Any::class
val clazz: KClass<*>,
val property: String = "",
val skip: Boolean = false,
val handler: String = "",
val handleClass: KClass<*> = Any::class,
)

View File

@ -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,
)

View File

@ -8,22 +8,22 @@ import kotlin.reflect.KProperty
* 自动调用updateValue方法更新值
*/
class AutoUpdatableMutableDelegatedField<in T, V : Any>(
override val delegatedField: MutableDelegatedField<T, V?>,
val updateValue: T.(property: KProperty<*>) -> V,
override val delegatedField: MutableDelegatedField<T, V?>,
val updateValue: T.(property: KProperty<*>) -> V,
) : MutableDelegatedField<T, V> by delegatedField.uncheckedCast(),
DecoratorMutableDelegatedField<T, V?> {
override fun getValue(thisRef: T, property: KProperty<*>): V {
var value = delegatedField.getValue(thisRef, property)
if (value == null) {
value = thisRef.updateValue(property)
delegatedField.setValue(thisRef, property, value)
}
return value
DecoratorMutableDelegatedField<T, V?> {
override fun getValue(thisRef: T, property: KProperty<*>): V {
var value = delegatedField.getValue(thisRef, property)
if (value == null) {
value = thisRef.updateValue(property)
delegatedField.setValue(thisRef, property, value)
}
return value
}
}
fun <T, V : Any> MutableDelegatedField<T, V?>.autoUpdate(
updateValue: T.(property: KProperty<*>) -> V,
updateValue: T.(property: KProperty<*>) -> V,
): MutableDelegatedField<T, V> {
return AutoUpdatableMutableDelegatedField(this, updateValue)
return AutoUpdatableMutableDelegatedField(this, updateValue)
}

View File

@ -3,10 +3,10 @@ package cn.tursom.core.delegation
import kotlin.reflect.KProperty
interface DecoratorDelegateProvider<in T, out V> :
DelegateProvider<T, DelegatedField<T, V>>,
DecoratorDelegatedField<T, V> {
override operator fun provideDelegate(
thisRef: T,
prop: KProperty<*>,
): DelegatedField<T, V> = delegatedField
DelegateProvider<T, DelegatedField<T, V>>,
DecoratorDelegatedField<T, V> {
override operator fun provideDelegate(
thisRef: T,
prop: KProperty<*>,
): DelegatedField<T, V> = delegatedField
}

View File

@ -3,9 +3,9 @@ package cn.tursom.core.delegation
import kotlin.reflect.KProperty
interface DecoratorMutableDelegateProvider<in T, V> :
DelegateProvider<T, MutableDelegatedField<T, V>>,
//DecoratorProvideDelegate<T, V>,
DecoratorMutableDelegatedField<T, V> {
override operator fun provideDelegate(thisRef: T, prop: KProperty<*>): MutableDelegatedField<T, V> =
delegatedField
DelegateProvider<T, MutableDelegatedField<T, V>>,
//DecoratorProvideDelegate<T, V>,
DecoratorMutableDelegatedField<T, V> {
override operator fun provideDelegate(thisRef: T, prop: KProperty<*>): MutableDelegatedField<T, V> =
delegatedField
}

View File

@ -1,5 +1,5 @@
package cn.tursom.core.delegation
interface DecoratorMutableDelegatedField<in T, V> : DecoratorDelegatedField<T, V> {
override val delegatedField: MutableDelegatedField<T, V>
override val delegatedField: MutableDelegatedField<T, V>
}

View File

@ -3,5 +3,5 @@ package cn.tursom.core.delegation
import kotlin.reflect.KProperty
interface DelegateProvider<in T, out R> {
operator fun provideDelegate(thisRef: T, prop: KProperty<*>): R
operator fun provideDelegate(thisRef: T, prop: KProperty<*>): R
}

View File

@ -7,14 +7,14 @@ class ExecutorMutableDelegatedField<in T, V>(
override val delegatedField: MutableDelegatedField<T, V>,
private val executor: Executor,
) : MutableDelegatedField<T, V> by delegatedField, DecoratorMutableDelegatedField<T, V> {
override fun valueOnSet(thisRef: T, property: KProperty<*>, value: V, oldValue: V) {
executor.execute {
delegatedField.valueOnSet(thisRef, property, value, oldValue)
}
override fun valueOnSet(thisRef: T, property: KProperty<*>, value: V, oldValue: V) {
executor.execute {
delegatedField.valueOnSet(thisRef, property, value, oldValue)
}
}
override fun setValue(thisRef: T, property: KProperty<*>, value: V) {
valueOnSet(thisRef, property, value, getValue())
delegatedField.setValue(value)
}
override fun setValue(thisRef: T, property: KProperty<*>, value: V) {
valueOnSet(thisRef, property, value, getValue())
delegatedField.setValue(value)
}
}

View File

@ -8,39 +8,39 @@ class ExpirableMutableDelegatedField<in T, V : Any>(
override val delegatedField: MutableDelegatedField<T, V>,
val expireMS: Long,
) : MutableDelegatedField<T, V?> by delegatedField.uncheckedCast(),
DecoratorMutableDelegatedField<T, V> {
DecoratorMutableDelegatedField<T, V> {
@Volatile
private var setTime: Long = 0L
@Volatile
private var setTime: Long = 0L
override fun getValue(thisRef: T, property: KProperty<*>): V? {
return if (System.currentTimeMillis() - setTime < expireMS) {
delegatedField.uncheckedCast<MutableDelegatedField<T, V?>>().getValue(thisRef, property)
} else {
null
}
override fun getValue(thisRef: T, property: KProperty<*>): V? {
return if (System.currentTimeMillis() - setTime < expireMS) {
delegatedField.uncheckedCast<MutableDelegatedField<T, V?>>().getValue(thisRef, property)
} else {
null
}
}
override fun setValue(thisRef: T, property: KProperty<*>, value: V?) {
if (value != null) {
delegatedField.setValue(value)
setTime = System.currentTimeMillis()
}
override fun setValue(thisRef: T, property: KProperty<*>, value: V?) {
if (value != null) {
delegatedField.setValue(value)
setTime = System.currentTimeMillis()
}
}
}
fun <T, V : Any> MutableDelegatedField<T, V>.expirable(
expireTime: Long,
timeUnit: TimeUnit = TimeUnit.MILLISECONDS,
expireTime: Long,
timeUnit: TimeUnit = TimeUnit.MILLISECONDS,
): MutableDelegatedField<T, V?> {
return ExpirableMutableDelegatedField(this, timeUnit.toMillis(expireTime))
return ExpirableMutableDelegatedField(this, timeUnit.toMillis(expireTime))
}
@JvmName("expirableTV?")
fun <T, V : Any> MutableDelegatedField<T, V?>.expirable(
expireTime: Long,
timeUnit: TimeUnit = TimeUnit.MILLISECONDS,
expireTime: Long,
timeUnit: TimeUnit = TimeUnit.MILLISECONDS,
): MutableDelegatedField<T, V?> {
return ExpirableMutableDelegatedField(uncheckedCast(), timeUnit.toMillis(expireTime))
return ExpirableMutableDelegatedField(uncheckedCast(), timeUnit.toMillis(expireTime))
}

View File

@ -3,8 +3,8 @@ package cn.tursom.core.delegation
import kotlin.reflect.KProperty
class GetterDelegatedField<in T, out V>(
override val delegatedField: DelegatedField<T, V>,
private val getter: DelegatedField<T, V>.(thisRef: T, property: KProperty<*>) -> V,
override val delegatedField: DelegatedField<T, V>,
private val getter: DelegatedField<T, V>.(thisRef: T, property: KProperty<*>) -> V,
) : DelegatedField<T, V> by delegatedField, DecoratorDelegatedField<T, V> {
override fun getValue(thisRef: T, property: KProperty<*>): V = delegatedField.getter(thisRef, property)
override fun getValue(thisRef: T, property: KProperty<*>): V = delegatedField.getter(thisRef, property)
}

View File

@ -6,5 +6,5 @@ class GetterMutableDelegatedField<in T, V>(
override val delegatedField: MutableDelegatedField<T, V>,
private val getter: MutableDelegatedField<T, V>.(thisRef: T, property: KProperty<*>) -> V,
) : MutableDelegatedField<T, V> by delegatedField, DecoratorMutableDelegatedField<T, V> {
override fun getValue(thisRef: T, property: KProperty<*>): V = delegatedField.getter(thisRef, property)
override fun getValue(thisRef: T, property: KProperty<*>): V = delegatedField.getter(thisRef, property)
}

View File

@ -3,8 +3,8 @@ package cn.tursom.core.delegation
import kotlin.reflect.KMutableProperty0
class KPropertyMutableDelegatedField<in T, V>(
val delegation: KMutableProperty0<V>,
val delegation: KMutableProperty0<V>,
) : MutableDelegatedField<T, V> {
override fun getValue(): V = delegation.get()
override fun setValue(value: V) = delegation.set(value)
override fun getValue(): V = delegation.get()
override fun setValue(value: V) = delegation.set(value)
}

View File

@ -7,22 +7,22 @@ class NotNullMutableDelegatedField<in T, V : Any>(
override val delegatedField: MutableDelegatedField<T, V?>,
val ifNull: () -> Nothing = { throw NullPointerException() },
) : MutableDelegatedField<T, V> by delegatedField.uncheckedCast(), DecoratorMutableDelegatedField<T, V?> {
override fun getValue(): V {
val value = delegatedField.getValue()
if (value == null) {
ifNull()
} else {
return value
}
override fun getValue(): V {
val value = delegatedField.getValue()
if (value == null) {
ifNull()
} else {
return value
}
}
override fun getValue(thisRef: T, property: KProperty<*>): V {
val value = delegatedField.getValue(thisRef, property)
if (value == null) {
ifNull()
} else {
return value
}
override fun getValue(thisRef: T, property: KProperty<*>): V {
val value = delegatedField.getValue(thisRef, property)
if (value == null) {
ifNull()
} else {
return value
}
}
}

View File

@ -5,45 +5,45 @@ import cn.tursom.core.uncheckedCast
import java.lang.reflect.Field
class ReflectionDelegatedField<in T, V>(
private val receiver: T,
private val field: Field,
private val receiver: T,
private val field: Field,
) : MutableDelegatedField<T, V> {
init {
field.isAccessible = true
init {
field.isAccessible = true
}
override fun getValue(): V = field.get(receiver).uncheckedCast()
override fun setValue(value: V) {
field.set(receiver, value)
}
companion object {
fun <T : Any, V> T.superField(
fieldName: String,
): MutableDelegatedField<T, V> {
return ReflectionDelegatedField(this, this.javaClass.getFieldForAll(fieldName)!!)
}
override fun getValue(): V = field.get(receiver).uncheckedCast()
override fun setValue(value: V) {
field.set(receiver, value)
fun <T, V> T.field(
field: Field,
): MutableDelegatedField<T, V> {
return ReflectionDelegatedField(this, field)
}
companion object {
fun <T : Any, V> T.superField(
fieldName: String,
): MutableDelegatedField<T, V> {
return ReflectionDelegatedField(this, this.javaClass.getFieldForAll(fieldName)!!)
}
fun <T, V> T.field(
field: Field,
): MutableDelegatedField<T, V> {
return ReflectionDelegatedField(this, field)
}
fun <T, V> T.field(
field: Field,
type: V,
): MutableDelegatedField<T, V> {
return ReflectionDelegatedField(this, field)
}
inline fun <T, V> T.field(
field: Field,
type: () -> V,
): MutableDelegatedField<T, V> {
return ReflectionDelegatedField(this, field)
}
fun <T, V> T.field(
field: Field,
type: V,
): MutableDelegatedField<T, V> {
return ReflectionDelegatedField(this, field)
}
inline fun <T, V> T.field(
field: Field,
type: () -> V,
): MutableDelegatedField<T, V> {
return ReflectionDelegatedField(this, field)
}
}
}

View File

@ -5,25 +5,25 @@ import cn.tursom.core.uncheckedCast
import kotlin.reflect.KProperty0
class SimpThreadLocalMutableDelegatedField<in T, V : Any>(
private val threadLocal: SimpThreadLocal<V>,
private val threadLocal: SimpThreadLocal<V>,
) : MutableDelegatedField<T, V> {
constructor(new: () -> V) : this(SimpThreadLocal(new = new))
constructor(new: () -> V) : this(SimpThreadLocal(new = new))
override fun <K> get(key: DelegatedFieldAttachmentKey<K>): K? {
return if (key == Companion || key == ThreadLocalMutableDelegatedField) {
threadLocal.uncheckedCast()
} else {
super.get(key)
}
override fun <K> get(key: DelegatedFieldAttachmentKey<K>): K? {
return if (key == Companion || key == ThreadLocalMutableDelegatedField) {
threadLocal.uncheckedCast()
} else {
super.get(key)
}
}
override fun setValue(value: V) = threadLocal.set(value)
override fun getValue(): V = threadLocal.get()
override fun setValue(value: V) = threadLocal.set(value)
override fun getValue(): V = threadLocal.get()
companion object : DelegatedFieldAttachmentKey<SimpThreadLocal<*>> {
fun <T : Any> getKey() = this.uncheckedCast<DelegatedFieldAttachmentKey<SimpThreadLocal<T>>>()
fun <T : Any> getKey(property: KProperty0<T>) =
this.uncheckedCast<DelegatedFieldAttachmentKey<SimpThreadLocal<T>>>()
}
companion object : DelegatedFieldAttachmentKey<SimpThreadLocal<*>> {
fun <T : Any> getKey() = this.uncheckedCast<DelegatedFieldAttachmentKey<SimpThreadLocal<T>>>()
fun <T : Any> getKey(property: KProperty0<T>) =
this.uncheckedCast<DelegatedFieldAttachmentKey<SimpThreadLocal<T>>>()
}
}

View File

@ -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")

View File

@ -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
@ -10,18 +10,18 @@ import java.sql.Types
@Suppress("MemberVisibilityCanBePrivate")
class JsonType<T : Any>(
val clazz: Type,
type: Int = Types.VARCHAR,
val gson: Gson = Utils.gson
val clazz: Type,
type: Int = Types.VARCHAR,
val gson: Gson = Utils.gson,
) : SqlType<T>(type, "json") {
constructor(clazz: Class<T>, type: Int = Types.VARCHAR) : this(clazz as Type, type)
constructor(clazz: Class<T>, type: Int = Types.VARCHAR) : this(clazz as Type, type)
override fun doGetResult(rs: ResultSet, index: Int): T? {
val result = rs.getString(index) ?: return null
return gson.fromJson(result, clazz)
}
override fun doGetResult(rs: ResultSet, index: Int): T? {
val result = rs.getString(index) ?: return null
return gson.fromJson(result, clazz)
}
override fun doSetParameter(ps: PreparedStatement, index: Int, parameter: T) {
ps.setString(index, gson.toJson(parameter))
}
override fun doSetParameter(ps: PreparedStatement, index: Int, parameter: T) {
ps.setString(index, gson.toJson(parameter))
}
}

View File

@ -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
@ -45,107 +44,107 @@ inline fun <reified T : Any> Query.getOne(): T? = if (rowSet.next()) {
}
fun <C : Any, E : Any> BaseTable<E>.json(
field: KProperty1<E, C?>,
type: Int = Types.VARCHAR,
gson: Gson = Utils.gson,
field: KProperty1<E, C?>,
type: Int = Types.VARCHAR,
gson: Gson = Utils.gson,
): Column<C> {
val sqlType = JsonType<C>(field.returnType.javaType, type, gson)
return this.registerColumn(field.simpTableField, sqlType)
}
fun <E : Any> BaseTable<E>.boolean(
field: KProperty1<E, Boolean?>,
field: KProperty1<E, Boolean?>,
) = boolean(field.simpTableField)
fun <E : Any> BaseTable<E>.int(
field: KProperty1<E, Int?>,
field: KProperty1<E, Int?>,
) = int(field.simpTableField)
fun <E : Any> BaseTable<E>.long(
field: KProperty1<E, Long?>,
field: KProperty1<E, Long?>,
) = long(field.simpTableField)
fun <E : Any> BaseTable<E>.float(
field: KProperty1<E, Float?>,
field: KProperty1<E, Float?>,
) = float(field.simpTableField)
fun <E : Any> BaseTable<E>.double(
field: KProperty1<E, Double?>,
field: KProperty1<E, Double?>,
) = double(field.simpTableField)
fun <E : Any> BaseTable<E>.decimal(
field: KProperty1<E, BigDecimal?>,
field: KProperty1<E, BigDecimal?>,
) = decimal(field.simpTableField)
fun <E : Any> BaseTable<E>.varchar(
field: KProperty1<E, String?>,
field: KProperty1<E, String?>,
) = varchar(field.simpTableField)
fun <E : Any> BaseTable<E>.text(
field: KProperty1<E, String?>,
field: KProperty1<E, String?>,
) = text(field.simpTableField)
fun <E : Any> BaseTable<E>.blob(
field: KProperty1<E, ByteArray?>,
field: KProperty1<E, ByteArray?>,
) = blob(field.simpTableField)
fun <E : Any> BaseTable<E>.bytes(
field: KProperty1<E, ByteArray?>,
field: KProperty1<E, ByteArray?>,
) = bytes(field.simpTableField)
fun <E : Any> BaseTable<E>.jdbcTimestamp(
field: KProperty1<E, Timestamp?>,
field: KProperty1<E, Timestamp?>,
) = jdbcTimestamp(field.simpTableField)
fun <E : Any> BaseTable<E>.jdbcDate(
field: KProperty1<E, Date?>,
field: KProperty1<E, Date?>,
) = jdbcDate(field.simpTableField)
fun <E : Any> BaseTable<E>.jdbcTime(
field: KProperty1<E, Time?>,
field: KProperty1<E, Time?>,
) = jdbcTime(field.simpTableField)
fun <E : Any> BaseTable<E>.timestamp(
field: KProperty1<E, Instant?>,
field: KProperty1<E, Instant?>,
) = timestamp(field.simpTableField)
fun <E : Any> BaseTable<E>.datetime(
field: KProperty1<E, LocalDateTime?>,
field: KProperty1<E, LocalDateTime?>,
) = datetime(field.simpTableField)
fun <E : Any> BaseTable<E>.date(
field: KProperty1<E, LocalDate?>,
field: KProperty1<E, LocalDate?>,
) = date(field.simpTableField)
fun <E : Any> BaseTable<E>.time(
field: KProperty1<E, LocalTime?>,
field: KProperty1<E, LocalTime?>,
) = time(field.simpTableField)
fun <E : Any> BaseTable<E>.monthDay(
field: KProperty1<E, MonthDay?>,
field: KProperty1<E, MonthDay?>,
) = monthDay(field.simpTableField)
fun <E : Any> BaseTable<E>.yearMonth(
field: KProperty1<E, YearMonth?>,
field: KProperty1<E, YearMonth?>,
) = yearMonth(field.simpTableField)
fun <E : Any> BaseTable<E>.year(
field: KProperty1<E, Year?>,
field: KProperty1<E, Year?>,
) = year(field.simpTableField)
fun <E : Any> BaseTable<E>.uuid(
field: KProperty1<E, UUID?>,
field: KProperty1<E, UUID?>,
) = uuid(field.simpTableField)
fun <E : Any, C : Enum<C>> BaseTable<E>.enum(
field: KProperty1<E, C?>,
typeRef: TypeReference<C>,
field: KProperty1<E, C?>,
typeRef: TypeReference<C>,
) = enum(field.simpTableField, typeRef)
fun <E : Any, C : Enum<C>> BaseTable<E>.enum(
field: KProperty1<E, C?>,
type: Class<C>,
field: KProperty1<E, C?>,
type: Class<C>,
) = registerColumn(field.simpTableField, EnumSqlType(type))

View 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()
}

View File

@ -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()
}
}

View File

@ -8,18 +8,18 @@ import kotlin.reflect.KProperty1
* 将属性转化为表列的适配器
*/
interface TypeAdapter<T : Any> {
/**
* 该适配器的优先级优先级越高则越优先匹配
* 同等优先级先注册者先匹配
*/
val level: Int get() = 0
/**
* 该适配器的优先级优先级越高则越优先匹配
* 同等优先级先注册者先匹配
*/
val level: Int get() = 0
/**
* 注册列
* 如果失败则返回null
*/
fun register(
table: BaseTable<Any>,
field: KProperty1<Any, T>
): Column<T>?
/**
* 注册列
* 如果失败则返回null
*/
fun register(
table: BaseTable<Any>,
field: KProperty1<Any, T>,
): Column<T>?
}

View File

@ -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
@ -14,63 +14,63 @@ import kotlin.reflect.full.isSubclassOf
* 注册类型适配器的工厂
*/
object TypeAdapterFactory {
private val adapterMap = ConcurrentSkipListMap<Int, MutableSet<TypeAdapter<*>>>()
private val adapterMap = ConcurrentSkipListMap<Int, MutableSet<TypeAdapter<*>>>()
init {
scanPackage(TypeAdapterFactory::class.java.`package`.name + ".typeadapter")
init {
scanPackage(TypeAdapterFactory::class.java.`package`.name + ".typeadapter")
}
private fun getAdapterQueue(level: Int): MutableCollection<TypeAdapter<*>> {
var set = adapterMap[-level]
if (set == null) {
synchronized(this) {
adapterMap[-level] = CopyOnWriteArraySet()
set = adapterMap[-level]!!
}
}
return set!!
}
private fun getAdapterQueue(level: Int): MutableCollection<TypeAdapter<*>> {
var set = adapterMap[-level]
if (set == null) {
synchronized(this) {
adapterMap[-level] = CopyOnWriteArraySet()
set = adapterMap[-level]!!
}
/**
* 扫描包并注册适配器
*/
fun scanPackage(
pkg: String,
classLoader: ClassLoader = this.javaClass.classLoader,
) {
classLoader.getClassByPackage(pkg).forEach {
try {
val clazz = Class.forName(it).kotlin
if (clazz.isSubclassOf(TypeAdapter::class)) {
val adapter: TypeAdapter<*> = InstantAllocator[clazz].uncheckedCast()
registerAdapter(adapter)
}
return set!!
} catch (e: Throwable) {
}
}
}
/**
* 扫描包并注册适配器
*/
fun scanPackage(
pkg: String,
classLoader: ClassLoader = this.javaClass.classLoader,
) {
classLoader.getClassByPackage(pkg).forEach {
try {
val clazz = Class.forName(it).kotlin
if (clazz.isSubclassOf(TypeAdapter::class)) {
val adapter: TypeAdapter<*> = InstantAllocator[clazz].uncheckedCast()
registerAdapter(adapter)
}
} catch (e: Throwable) {
}
/**
* 注册适配器实例
*/
fun registerAdapter(adapter: TypeAdapter<*>) {
getAdapterQueue(adapter.level).add(adapter)
}
fun register(
table: BaseTable<*>,
field: KProperty1<*, *>,
): Column<*>? {
adapterMap.forEach { (_, queue) ->
queue.forEach {
val column = it.register(table.uncheckedCast(), field.uncheckedCast())
if (column != null) {
return column
}
}
}
return null
}
/**
* 注册适配器实例
*/
fun registerAdapter(adapter: TypeAdapter<*>) {
getAdapterQueue(adapter.level).add(adapter)
}
fun register(
table: BaseTable<*>,
field: KProperty1<*, *>,
): Column<*>? {
adapterMap.forEach { (_, queue) ->
queue.forEach {
val column = it.register(table.uncheckedCast(), field.uncheckedCast())
if (column != null) {
return column
}
}
}
return null
}
override fun toString() = adapterMap.toString()
override fun toString() = adapterMap.toString()
}

View 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())

View File

@ -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<*>)

View File

@ -1,6 +1,5 @@
package cn.tursom.database.annotations
@MustBeDocumented
@Retention(AnnotationRetention.RUNTIME)
@Target(AnnotationTarget.PROPERTY)

View File

@ -8,13 +8,13 @@ import kotlin.reflect.KProperty1
import kotlin.reflect.jvm.jvmErasure
object BooleanAdapter : TypeAdapter<Boolean> {
override fun register(table: BaseTable<Any>, field: KProperty1<Any, Boolean>): Column<Boolean>? {
return if (field.returnType.jvmErasure == Boolean::class) {
table.boolean(field)
} else {
null
}
override fun register(table: BaseTable<Any>, field: KProperty1<Any, Boolean>): Column<Boolean>? {
return if (field.returnType.jvmErasure == Boolean::class) {
table.boolean(field)
} else {
null
}
}
override fun toString() = "BooleanAdapter"
override fun toString() = "BooleanAdapter"
}

View File

@ -8,13 +8,13 @@ import kotlin.reflect.KProperty1
import kotlin.reflect.jvm.jvmErasure
object BytesAdapter : TypeAdapter<ByteArray> {
override fun register(table: BaseTable<Any>, field: KProperty1<Any, ByteArray>): Column<ByteArray>? {
return if (field.returnType.jvmErasure == ByteArray::class) {
table.bytes(field)
} else {
null
}
override fun register(table: BaseTable<Any>, field: KProperty1<Any, ByteArray>): Column<ByteArray>? {
return if (field.returnType.jvmErasure == ByteArray::class) {
table.bytes(field)
} else {
null
}
}
override fun toString() = "BytesAdapter"
override fun toString() = "BytesAdapter"
}

View File

@ -9,13 +9,13 @@ import kotlin.reflect.KProperty1
import kotlin.reflect.jvm.jvmErasure
object DateAdapter : TypeAdapter<Date> {
override fun register(table: BaseTable<Any>, field: KProperty1<Any, Date>): Column<Date>? {
return if (field.returnType.jvmErasure == Date::class) {
table.jdbcDate(field)
} else {
null
}
override fun register(table: BaseTable<Any>, field: KProperty1<Any, Date>): Column<Date>? {
return if (field.returnType.jvmErasure == Date::class) {
table.jdbcDate(field)
} else {
null
}
}
override fun toString() = "DateAdapter"
override fun toString() = "DateAdapter"
}

View File

@ -8,13 +8,13 @@ import kotlin.reflect.KProperty1
import kotlin.reflect.jvm.jvmErasure
object DoubleAdapter : TypeAdapter<Double> {
override fun register(table: BaseTable<Any>, field: KProperty1<Any, Double>): Column<Double>? {
return if (field.returnType.jvmErasure == Double::class) {
table.double(field)
} else {
null
}
override fun register(table: BaseTable<Any>, field: KProperty1<Any, Double>): Column<Double>? {
return if (field.returnType.jvmErasure == Double::class) {
table.double(field)
} else {
null
}
}
override fun toString() = "DoubleAdapter"
override fun toString() = "DoubleAdapter"
}

View File

@ -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
@ -11,18 +11,18 @@ import kotlin.reflect.full.isSubclassOf
import kotlin.reflect.jvm.jvmErasure
object EnumAdapter : TypeAdapter<EnumAdapter.EnumType> {
enum class EnumType
enum class EnumType
override fun register(table: BaseTable<Any>, field: KProperty1<Any, EnumType>): Column<EnumType>? {
val kClass = field.returnType.jvmErasure
return if (kClass.isSubclassOf(Enum::class)) {
table.registerColumn(field.simpTableField, EnumSqlType<EnumType>(kClass.java.uncheckedCast()))
.uncheckedCast()
} else {
null
}
override fun register(table: BaseTable<Any>, field: KProperty1<Any, EnumType>): Column<EnumType>? {
val kClass = field.returnType.jvmErasure
return if (kClass.isSubclassOf(Enum::class)) {
table.registerColumn(field.simpTableField, EnumSqlType<EnumType>(kClass.java.uncheckedCast()))
.uncheckedCast()
} else {
null
}
}
override fun toString() = "EnumAdapter"
override fun toString() = "EnumAdapter"
}

View File

@ -8,13 +8,13 @@ import kotlin.reflect.KProperty1
import kotlin.reflect.jvm.jvmErasure
object FloatAdapter : TypeAdapter<Float> {
override fun register(table: BaseTable<Any>, field: KProperty1<Any, Float>): Column<Float>? {
return if (field.returnType.jvmErasure == Float::class) {
table.float(field)
} else {
null
}
override fun register(table: BaseTable<Any>, field: KProperty1<Any, Float>): Column<Float>? {
return if (field.returnType.jvmErasure == Float::class) {
table.float(field)
} else {
null
}
}
override fun toString() = "FloatAdapter"
override fun toString() = "FloatAdapter"
}

View File

@ -9,13 +9,13 @@ import kotlin.reflect.KProperty1
import kotlin.reflect.jvm.jvmErasure
object InstantAdapter : TypeAdapter<Instant> {
override fun register(table: BaseTable<Any>, field: KProperty1<Any, Instant>): Column<Instant>? {
return if (field.returnType.jvmErasure == Instant::class) {
table.timestamp(field)
} else {
null
}
override fun register(table: BaseTable<Any>, field: KProperty1<Any, Instant>): Column<Instant>? {
return if (field.returnType.jvmErasure == Instant::class) {
table.timestamp(field)
} else {
null
}
}
override fun toString() = "InstantAdapter"
override fun toString() = "InstantAdapter"
}

View File

@ -8,13 +8,13 @@ import kotlin.reflect.KProperty1
import kotlin.reflect.jvm.jvmErasure
object IntAdapter : TypeAdapter<Int> {
override fun register(table: BaseTable<Any>, field: KProperty1<Any, Int>): Column<Int>? {
return if (field.returnType.jvmErasure == Int::class) {
table.int(field)
} else {
null
}
override fun register(table: BaseTable<Any>, field: KProperty1<Any, Int>): Column<Int>? {
return if (field.returnType.jvmErasure == Int::class) {
table.int(field)
} else {
null
}
}
override fun toString() = "IntAdapter"
override fun toString() = "IntAdapter"
}

View File

@ -9,13 +9,13 @@ import kotlin.reflect.KProperty1
import kotlin.reflect.jvm.jvmErasure
object IntAdapterAdapter : TypeAdapter<BigDecimal> {
override fun register(table: BaseTable<Any>, field: KProperty1<Any, BigDecimal>): Column<BigDecimal>? {
return if (field.returnType.jvmErasure == BigDecimal::class) {
table.decimal(field)
} else {
null
}
override fun register(table: BaseTable<Any>, field: KProperty1<Any, BigDecimal>): Column<BigDecimal>? {
return if (field.returnType.jvmErasure == BigDecimal::class) {
table.decimal(field)
} else {
null
}
}
override fun toString() = "IntAdapterAdapter"
override fun toString() = "IntAdapterAdapter"
}

View File

@ -9,15 +9,15 @@ import kotlin.reflect.KProperty1
import kotlin.reflect.full.findAnnotation
object JsonAdapter : TypeAdapter<Int> {
override val level: Int get() = -16
override val level: Int get() = -16
override fun register(table: BaseTable<Any>, field: KProperty1<Any, Int>): Column<Int>? {
return if (field.findAnnotation<Json>() != null) {
table.json(field)
} else {
null
}
override fun register(table: BaseTable<Any>, field: KProperty1<Any, Int>): Column<Int>? {
return if (field.findAnnotation<Json>() != null) {
table.json(field)
} else {
null
}
}
override fun toString() = "JsonAdapter"
override fun toString() = "JsonAdapter"
}

View File

@ -9,13 +9,13 @@ import kotlin.reflect.KProperty1
import kotlin.reflect.jvm.jvmErasure
object LocalDateAdapter : TypeAdapter<LocalDate> {
override fun register(table: BaseTable<Any>, field: KProperty1<Any, LocalDate>): Column<LocalDate>? {
return if (field.returnType.jvmErasure == LocalDate::class) {
table.date(field)
} else {
null
}
override fun register(table: BaseTable<Any>, field: KProperty1<Any, LocalDate>): Column<LocalDate>? {
return if (field.returnType.jvmErasure == LocalDate::class) {
table.date(field)
} else {
null
}
}
override fun toString() = "LocalDateAdapter"
override fun toString() = "LocalDateAdapter"
}

View File

@ -9,13 +9,13 @@ import kotlin.reflect.KProperty1
import kotlin.reflect.jvm.jvmErasure
object LocalDateTimeAdapter : TypeAdapter<LocalDateTime> {
override fun register(table: BaseTable<Any>, field: KProperty1<Any, LocalDateTime>): Column<LocalDateTime>? {
return if (field.returnType.jvmErasure == LocalDateTime::class) {
table.datetime(field)
} else {
null
}
override fun register(table: BaseTable<Any>, field: KProperty1<Any, LocalDateTime>): Column<LocalDateTime>? {
return if (field.returnType.jvmErasure == LocalDateTime::class) {
table.datetime(field)
} else {
null
}
}
override fun toString() = "LocalDateTimeAdapter"
override fun toString() = "LocalDateTimeAdapter"
}

View File

@ -9,13 +9,13 @@ import kotlin.reflect.KProperty1
import kotlin.reflect.jvm.jvmErasure
object LocalTimeAdapter : TypeAdapter<LocalTime> {
override fun register(table: BaseTable<Any>, field: KProperty1<Any, LocalTime>): Column<LocalTime>? {
return if (field.returnType.jvmErasure == LocalTime::class) {
table.time(field)
} else {
null
}
override fun register(table: BaseTable<Any>, field: KProperty1<Any, LocalTime>): Column<LocalTime>? {
return if (field.returnType.jvmErasure == LocalTime::class) {
table.time(field)
} else {
null
}
}
override fun toString() = "LocalTimeAdapter"
override fun toString() = "LocalTimeAdapter"
}

View File

@ -8,13 +8,13 @@ import kotlin.reflect.KProperty1
import kotlin.reflect.jvm.jvmErasure
object LongAdapter : TypeAdapter<Long> {
override fun register(table: BaseTable<Any>, field: KProperty1<Any, Long>): Column<Long>? {
return if (field.returnType.jvmErasure == Long::class) {
table.long(field)
} else {
null
}
override fun register(table: BaseTable<Any>, field: KProperty1<Any, Long>): Column<Long>? {
return if (field.returnType.jvmErasure == Long::class) {
table.long(field)
} else {
null
}
}
override fun toString() = "LongAdapter"
override fun toString() = "LongAdapter"
}

View File

@ -9,13 +9,13 @@ import kotlin.reflect.KProperty1
import kotlin.reflect.jvm.jvmErasure
object MonthDayAdapter : TypeAdapter<MonthDay> {
override fun register(table: BaseTable<Any>, field: KProperty1<Any, MonthDay>): Column<MonthDay>? {
return if (field.returnType.jvmErasure == MonthDay::class) {
table.monthDay(field)
} else {
null
}
override fun register(table: BaseTable<Any>, field: KProperty1<Any, MonthDay>): Column<MonthDay>? {
return if (field.returnType.jvmErasure == MonthDay::class) {
table.monthDay(field)
} else {
null
}
}
override fun toString() = "MonthDayAdapter"
override fun toString() = "MonthDayAdapter"
}

View File

@ -8,13 +8,13 @@ import kotlin.reflect.KProperty1
import kotlin.reflect.jvm.jvmErasure
object StringAdapter : TypeAdapter<String> {
override fun register(table: BaseTable<Any>, field: KProperty1<Any, String>): Column<String>? {
return if (field.returnType.jvmErasure == String::class) {
table.varchar(field)
} else {
null
}
override fun register(table: BaseTable<Any>, field: KProperty1<Any, String>): Column<String>? {
return if (field.returnType.jvmErasure == String::class) {
table.varchar(field)
} else {
null
}
}
override fun toString() = "StringAdapter"
override fun toString() = "StringAdapter"
}

View File

@ -9,13 +9,13 @@ import kotlin.reflect.KProperty1
import kotlin.reflect.jvm.jvmErasure
object TimeAdapter : TypeAdapter<Time> {
override fun register(table: BaseTable<Any>, field: KProperty1<Any, Time>): Column<Time>? {
return if (field.returnType.jvmErasure == Time::class) {
table.jdbcTime(field)
} else {
null
}
override fun register(table: BaseTable<Any>, field: KProperty1<Any, Time>): Column<Time>? {
return if (field.returnType.jvmErasure == Time::class) {
table.jdbcTime(field)
} else {
null
}
}
override fun toString() = "TimeAdapter"
override fun toString() = "TimeAdapter"
}

View File

@ -9,13 +9,13 @@ import kotlin.reflect.KProperty1
import kotlin.reflect.jvm.jvmErasure
object TimestampAdapter : TypeAdapter<Timestamp> {
override fun register(table: BaseTable<Any>, field: KProperty1<Any, Timestamp>): Column<Timestamp>? {
return if (field.returnType.jvmErasure == Timestamp::class) {
table.jdbcTimestamp(field)
} else {
null
}
override fun register(table: BaseTable<Any>, field: KProperty1<Any, Timestamp>): Column<Timestamp>? {
return if (field.returnType.jvmErasure == Timestamp::class) {
table.jdbcTimestamp(field)
} else {
null
}
}
override fun toString() = "TimestampAdapter"
override fun toString() = "TimestampAdapter"
}

View File

@ -9,13 +9,13 @@ import kotlin.reflect.KProperty1
import kotlin.reflect.jvm.jvmErasure
object UUIDAdapter : TypeAdapter<UUID> {
override fun register(table: BaseTable<Any>, field: KProperty1<Any, UUID>): Column<UUID>? {
return if (field.returnType.jvmErasure == UUID::class) {
table.uuid(field)
} else {
null
}
override fun register(table: BaseTable<Any>, field: KProperty1<Any, UUID>): Column<UUID>? {
return if (field.returnType.jvmErasure == UUID::class) {
table.uuid(field)
} else {
null
}
}
override fun toString() = "UUIDAdapter"
override fun toString() = "UUIDAdapter"
}

View File

@ -9,13 +9,13 @@ import kotlin.reflect.KProperty1
import kotlin.reflect.jvm.jvmErasure
object YearAdapter : TypeAdapter<Year> {
override fun register(table: BaseTable<Any>, field: KProperty1<Any, Year>): Column<Year>? {
return if (field.returnType.jvmErasure == Year::class) {
table.year(field)
} else {
null
}
override fun register(table: BaseTable<Any>, field: KProperty1<Any, Year>): Column<Year>? {
return if (field.returnType.jvmErasure == Year::class) {
table.year(field)
} else {
null
}
}
override fun toString() = "YearAdapter"
override fun toString() = "YearAdapter"
}

View File

@ -9,13 +9,13 @@ import kotlin.reflect.KProperty1
import kotlin.reflect.jvm.jvmErasure
object YearMonthAdapter : TypeAdapter<YearMonth> {
override fun register(table: BaseTable<Any>, field: KProperty1<Any, YearMonth>): Column<YearMonth>? {
return if (field.returnType.jvmErasure == YearMonth::class) {
table.yearMonth(field)
} else {
null
}
override fun register(table: BaseTable<Any>, field: KProperty1<Any, YearMonth>): Column<YearMonth>? {
return if (field.returnType.jvmErasure == YearMonth::class) {
table.yearMonth(field)
} else {
null
}
}
override fun toString() = "YearMonthAdapter"
override fun toString() = "YearMonthAdapter"
}