[springboot:kotlin] mybatis common sql provider

公共接口

发现书写 mapper对数据库进行增删改查 以及 controller 都是重复性操作,才有了本编文章,主要是利用反射自动生成 SQL 增删改查语句

代码

import org.apache.ibatis.annotations.DeleteProvider
import org.apache.ibatis.annotations.InsertProvider
import org.apache.ibatis.annotations.Options
import org.apache.ibatis.annotations.UpdateProvider

interface HKBaseMapper<T> {
    @Options(useGeneratedKeys = true)
    @InsertProvider(type = HKSqlProvider::class, method = "insert")
    fun insert(tableModel: T): Int

    @DeleteProvider(type = HKSqlProvider::class, method = "delete")
    fun delete(tableModel: T): Int

    @UpdateProvider(type = HKSqlProvider::class, method = "update")
    fun update(tableModel: T): Int

    @UpdateProvider(type = HKSqlProvider::class, method = "select")
    fun select(tableModel: T): MutableList<T>
}

import org.apache.ibatis.annotations.Mapper

@Mapper
interface AdMapper : HKBaseMapper<AdModel>


import org.apache.logging.log4j.LogManager
import org.apache.logging.log4j.Logger

@Suppress("unused")
class HKSqlProvider {
    private val logger: Logger = LogManager.getLogger(UserController::class.java.name)

    fun insert(tableModel: Any?): String {
        val tableName = tableModel?.javaClass?.simpleName?.replace("Model", "")?.toLowerUnderScoreFromUpperCamel()
        val modelFields = HKReflectUtil.getFields(tableModel?.javaClass)
        val valueNameList = ArrayList<String>()
        val sqlString = StringBuilder("insert into $tableName (")
        modelFields.forEach { field -> HKReflectUtil.getValue(field, tableModel)?.let { valueNameList.add(field.name) } }
        valueNameList.forEachIndexed { index, valueName -> sqlString.append(valueName).append(if (index != valueNameList.size - 1) "," else ") values(") }
        valueNameList.forEachIndexed { index, valueName -> sqlString.append("#{$valueName}").append(if (index != valueNameList.size - 1) "," else ")") }

        logger.warn("""
            ---------------------------------
            mybatis-buildSql-insert -->
            tableModel: $tableModel
                   sql: $sqlString
            ---------------------------------
        """)
        return sqlString.toString()
    }

    fun update(tableModel: Any?): String {
        val tableName = tableModel?.javaClass?.simpleName?.replace("Model", "")?.toLowerUnderScoreFromUpperCamel()
        val modelFields = HKReflectUtil.getFields(tableModel?.javaClass)
        val valueNameList = ArrayList<String>()
        val sqlString = StringBuilder("update $tableName set ")
        modelFields.forEach { field -> HKReflectUtil.getValue(field, tableModel)?.let { valueNameList.add(field.name) } }
        valueNameList.forEachIndexed { index, valueName -> sqlString.append("$valueName=#{$valueName}").append(if (index != valueNameList.size - 1) "," else "") }

        logger.warn("""
            ---------------------------------
            mybatis-buildSql-update -->
            tableModel: $tableModel
                   sql: $sqlString
            ---------------------------------
        """)
        return sqlString.toString()
    }

    fun delete(tableModel: Any?): String {
        val tableName = tableModel?.javaClass?.simpleName?.replace("Model", "")?.toLowerUnderScoreFromUpperCamel()
        val modelFields = HKReflectUtil.getFields(tableModel?.javaClass)
        val valueNameList = ArrayList<String>()
        val sqlString = StringBuilder("delete from $tableName where ")
        modelFields.forEach { field -> HKReflectUtil.getValue(field, tableModel)?.let { valueNameList.add(field.name) } }
        valueNameList.forEachIndexed { index, valueName -> sqlString.append("$valueName=#{$valueName}").append(if (index != valueNameList.size - 1) " and " else "") }

        logger.warn("""
            ---------------------------------
            mybatis-buildSql-delete -->
            tableModel: $tableModel
                   sql: $sqlString
            ---------------------------------
        """)
        return sqlString.toString()
    }

    fun select(tableModel: Any?): String {
        val tableName = tableModel?.javaClass?.simpleName?.replace("Model", "")?.toLowerUnderScoreFromUpperCamel()
        val modelFields = HKReflectUtil.getFields(tableModel?.javaClass)
        val valueNameList = ArrayList<String>()
        val sqlString = StringBuilder("select * from $tableName where ")
        modelFields.forEach { field -> HKReflectUtil.getValue(field, tableModel)?.let { valueNameList.add(field.name) } }
        valueNameList.forEachIndexed { index, valueName -> sqlString.append("$valueName=#{$valueName}").append(if (index != valueNameList.size - 1) " and " else "") }

        logger.warn("""
            ---------------------------------
            mybatis-buildSql-select -->
            tableModel: $tableModel
                   sql: $sqlString
            ---------------------------------
        """)
        return sqlString.toString()
    }
}

import io.swagger.annotations.ApiOperation
import org.springframework.web.bind.annotation.PostMapping
import org.springframework.web.bind.annotation.RequestBody
import org.springframework.web.bind.annotation.RequestMapping
import org.springframework.web.bind.annotation.RestController


@RestController
@RequestMapping("/ad")
class AdController(val mapper: AdMapper) {

    @ApiOperation("增加", notes = "返回 ID")
    @PostMapping("/insert")
    fun insert(@RequestBody request: HKRequest<AdModel>): HKResponse<HKIdData> {
        if (request.data == null) return HKCode.ERROR_PARAMS.response()
        return HKResponse(HKIdData(mapper.insert(request.data!!)))
    }

    @ApiOperation("删除", notes = "返回 受影响的行数")
    @PostMapping("/delete")
    fun delete(@RequestBody request: HKRequest<AdModel>): HKResponse<HKColumnData> {
        if (request.data == null) return HKCode.ERROR_PARAMS.response(HKColumnData(-1))
        return HKResponse(HKColumnData(mapper.delete(request.data!!)))
    }

    @ApiOperation("修改", notes = "返回 受影响的行数")
    @PostMapping("/update")
    fun update(@RequestBody request: HKRequest<AdModel>): HKResponse<HKColumnData> {
        if (request.data == null) return HKCode.ERROR_PARAMS.response()
        return HKResponse(HKColumnData(mapper.update(request.data!!)))
    }

    @ApiOperation("查询")
    @PostMapping("/select")
    fun select(@RequestBody request: HKRequest<AdModel>): HKResponse<List<AdModel>> {
        if (request.data == null || request.data == null) return HKCode.ERROR_PARAMS.response()
        return HKResponse(mapper.select(request.data!!))
    }

}

反射工具类

import java.lang.reflect.Field
import java.lang.reflect.InvocationTargetException
import kotlin.reflect.KClass
import kotlin.reflect.full.companionObject
import kotlin.reflect.full.companionObjectInstance
import kotlin.reflect.full.declaredFunctions

@Suppress("unused")
object HKReflectUtil {
    private val TAG = "[reflect]"

    /**
     * 根据方法的名字调用方法,适合 object 定义的单例静态方法
     */
    @Throws(RuntimeException::class, IllegalAccessException::class, IllegalArgumentException::class, InvocationTargetException::class, NullPointerException::class, ExceptionInInitializerError::class)
    fun invoke(clazz: KClass<*>?, methodName: String?, vararg params: Any?): Any? {
        if (clazz == null || methodName.isNullOrBlank()) throw RuntimeException("${TAG} clazz:$clazz or methodName:$methodName is null")
        val methods = clazz.java.kotlin.companionObject?.declaredFunctions?.filter { it.name == methodName && it.parameters.size - 1 == params.size }
        if (methods?.size ?: 0 <= 0) throw RuntimeException("[callNativeMethod] the invoked method dose not exist :$methodName")
        return methods!![0].call(clazz.companionObjectInstance, *params)
    }

    fun getFields(objectClass: Class<*>?): MutableList<Field> {
        var fieldList: MutableList<Field>? = null
        try {
            fieldList = objectClass?.declaredFields?.toMutableList()
            objectClass?.superclass?.declaredFields.let { if (it != null) fieldList?.addAll(it) }
        } catch (ignore: Exception) {
        }
        return fieldList ?: arrayListOf()
    }

    fun getValue(field: Field?, fromObject: Any?): Any? = try {
        field?.isAccessible = true
        field?.get(fromObject)
    } catch (ignore: Exception) {
        null
    }
}

预览

swagger2
最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 217,406评论 6 503
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 92,732评论 3 393
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 163,711评论 0 353
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 58,380评论 1 293
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 67,432评论 6 392
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 51,301评论 1 301
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 40,145评论 3 418
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 39,008评论 0 276
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 45,443评论 1 314
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 37,649评论 3 334
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 39,795评论 1 347
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 35,501评论 5 345
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 41,119评论 3 328
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 31,731评论 0 22
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 32,865评论 1 269
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 47,899评论 2 370
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 44,724评论 2 354

推荐阅读更多精彩内容