前言
Mybatis-plus
提供的BaseMapper
中已经有频繁要使用的增删改查方法,比如selectById
、insert
等,但是有时候业务经常要用到某个模板sql,BaseMapper中又没有,MybatisPlus提供了Plugin入口,我们可以自定义BaseMapper来实现。比如,在某些table中有唯一约束键,当insert时如果唯一键冲突会抛错,如果恰好此时我们又不想处理这个错误,那我们希望使用insert ignore into ...
的语法, 但是BaseMapper没有提供这个sql的模板方法,此时需要我们自己去实现.
编写SQL模板
首先我们创建class InsertIgnore
,定义方法名称和对应生成SQL的模板,这里我使用kotlin编写,大家可以转成对应的java class
kotlin
代码解读
复制代码
import com.baomidou.mybatisplus.annotation.IdType import com.baomidou.mybatisplus.core.injector.AbstractMethod import com.baomidou.mybatisplus.core.metadata.TableInfo import com.baomidou.mybatisplus.core.metadata.TableInfoHelper import com.baomidou.mybatisplus.core.toolkit.StringPool import com.baomidou.mybatisplus.core.toolkit.StringUtils import com.baomidou.mybatisplus.core.toolkit.sql.SqlScriptUtils import org.apache.ibatis.executor.keygen.Jdbc3KeyGenerator import org.apache.ibatis.executor.keygen.KeyGenerator import org.apache.ibatis.executor.keygen.NoKeyGenerator import org.apache.ibatis.mapping.MappedStatement /** * 实现insert ignore into sql模板 */ class InsertIgnore : AbstractMethod() { companion object { const val METHOD_NAME = "insertIgnore" const val SQL_TEMPLATE = """ <script> INSERT IGNORE INTO %s %s VALUES %s </script> """ } override fun injectMappedStatement( mapperClass: Class<*>?, modelClass: Class<*>?, tableInfo: TableInfo? ): MappedStatement { var keyGenerator: KeyGenerator = NoKeyGenerator() val columnScript = SqlScriptUtils.convertTrim( tableInfo!!.allInsertSqlColumnMaybeIf, StringPool.LEFT_BRACKET, StringPool.RIGHT_BRACKET, null, StringPool.COMMA ) val valuesScript = SqlScriptUtils.convertTrim( tableInfo.getAllInsertSqlPropertyMaybeIf(null), StringPool.LEFT_BRACKET, StringPool.RIGHT_BRACKET, null, StringPool.COMMA ) var keyProperty: String? = null var keyColumn: String? = null // 表包含主键处理逻辑,如果不包含主键当普通字段处理 if (StringUtils.isNotBlank(tableInfo.keyProperty)) { if (tableInfo.idType == IdType.AUTO) { /** 自增主键 */ keyGenerator = Jdbc3KeyGenerator() keyProperty = tableInfo.keyProperty keyColumn = tableInfo.keyColumn } else { if (null != tableInfo.keySequence) { keyGenerator = TableInfoHelper.genKeyGenerator(METHOD_NAME, tableInfo, builderAssistant) keyProperty = tableInfo.keyProperty keyColumn = tableInfo.keyColumn } } } val sql = String.format(SQL_TEMPLATE, tableInfo.tableName, columnScript, valuesScript) val sqlSource = languageDriver.createSqlSource(configuration, sql, modelClass) return addInsertMappedStatement( mapperClass, modelClass, METHOD_NAME, sqlSource, keyGenerator, keyProperty, keyColumn ) } }
自定义Mapper
在自定义Mapper接口中添加insertIgnore方法
kotlin
代码解读
复制代码
import com.baomidou.mybatisplus.core.mapper.BaseMapper interface UltraBaseMapper<T> : BaseMapper<T> { /** * 插入一条数据,如果插入报错(比如唯一约束冲突) 则忽略 */ fun insertIgnore(entity: T): Int }
业务Mapper原来需要继承BaseMapper,改为继承UltraBaseMapper
kotlin
代码解读
复制代码
interface UserMapper : UltraBaseMapper<User>
这样UserMapper就拥有了insertIgnore方法,此时还缺少一项配置,那就是将我们的InsertIgnore这个class加入到MybatisPlus的插件中
配置插件
kotlin
代码解读
复制代码
import com.baomidou.mybatisplus.core.injector.AbstractMethod import com.baomidou.mybatisplus.core.injector.DefaultSqlInjector class UltraSqlInjector : DefaultSqlInjector() { override fun getMethodList(mapperClass: Class<*>?): MutableList<AbstractMethod> { val methodList = super.getMethodList(mapperClass) methodList.add(InsertIgnore()) return methodList } }
Spring配置
kotlin
代码解读
复制代码
import org.springframework.context.annotation.Bean import org.springframework.context.annotation.Configuration @Configuration class MybatisPlusConfig { @Bean fun ultraSqlInjector(): UltraSqlInjector { return UltraSqlInjector() } }
总结
可以通过继承mybatis-plus提供的AbstractMethod来实现自定义SQL模板,比如本文中的示例InsertIgnore,我还实现了InsertBatch
、InsertIgnoreBatch
、SelectByIdForUpdate
等